• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua Pokedash Pota Party System

maxsaenz95

New Member
Joined
May 18, 2010
Messages
30
Reaction score
4
Hello guys, im running a Pokedash POTA V1.2 server based on TFS 1.2 problem is party Shared experience not working, problem being the members are "inactive" all the time even if engaged in battle, shields blinking non stop
Lua:
    if (!player->hasFlag(PlayerFlag_NotGainInFight)) {
        //check if the player has healed/attacked anything recently
        auto it = ticksMap.find(player->getID());
        if (it == ticksMap.end()) {
            return false;
        }

        uint64_t timeDiff = OTSYS_TIME() - it->second;
        if (timeDiff > static_cast<uint64_t>(g_config.getNumber(ConfigManager::PZ_LOCKED))) {
            return false;
        }
    }
removing this doesnt work also
Post automatically merged:

party

Lua:
/**
 * The Forgotten Server - a free and open-source MMORPG server emulator
 * Copyright (C) 2016  Mark Samman <[email protected]>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "otpch.h"

#include "party.h"
#include "game.h"
#include "configmanager.h"
#include "events.h"

extern Game g_game;
extern ConfigManager g_config;
extern Events* g_events;

Party::Party(Player* leader) : leader(leader)
{
    leader->setParty(this);
}

void Party::disband()
{
    if (!g_events->eventPartyOnDisband(this)) {
        return;
    }

    Player* currentLeader = leader;
    leader = nullptr;

    currentLeader->setParty(nullptr);
    currentLeader->sendClosePrivate(CHANNEL_PARTY);
    g_game.updatePlayerShield(currentLeader);
    g_game.updatePlayerHelpers(*currentLeader);
    currentLeader->sendCreatureSkull(currentLeader);
    currentLeader->sendTextMessage(MESSAGE_INFO_DESCR, "Your party has been disbanded.");

    for (Player* invitee : inviteList) {
        invitee->removePartyInvitation(this);
        currentLeader->sendCreatureShield(invitee);
    }
    inviteList.clear();

    for (Player* member : memberList) {
        member->setParty(nullptr);
        member->sendClosePrivate(CHANNEL_PARTY);
        member->sendTextMessage(MESSAGE_INFO_DESCR, "Your party has been disbanded.");
    }

    for (Player* member : memberList) {
        g_game.updatePlayerShield(member);

        for (Player* otherMember : memberList) {
            otherMember->sendCreatureSkull(member);
        }

        member->sendCreatureSkull(currentLeader);
        currentLeader->sendCreatureSkull(member);
        g_game.updatePlayerHelpers(*member);
    }
    memberList.clear();
    delete this;
}

bool Party::leaveParty(Player* player)
{
    if (!player) {
        return false;
    }

    if (player->getParty() != this && leader != player) {
        return false;
    }

    if (!g_events->eventPartyOnLeave(this, player)) {
        return false;
    }

    bool missingLeader = false;
    if (leader == player) {
        if (!memberList.empty()) {
            if (memberList.size() == 1 && inviteList.empty()) {
                missingLeader = true;
            } else {
                passPartyLeadership(memberList.front());
            }
        } else {
            missingLeader = true;
        }
    }

    //since we already passed the leadership, we remove the player from the list
    auto it = std::find(memberList.begin(), memberList.end(), player);
    if (it != memberList.end()) {
        memberList.erase(it);
    }

    player->setParty(nullptr);
    player->sendClosePrivate(CHANNEL_PARTY);
    g_game.updatePlayerShield(player);
    g_game.updatePlayerHelpers(*player);

    for (Player* member : memberList) {
        member->sendCreatureSkull(player);
        player->sendPlayerPartyIcons(member);
        g_game.updatePlayerHelpers(*member);
    }

    leader->sendCreatureSkull(player);
    player->sendCreatureSkull(player);
    player->sendPlayerPartyIcons(leader);

    player->sendTextMessage(MESSAGE_INFO_DESCR, "You have left the party.");

    updateSharedExperience();
    updateVocationsList();

    clearPlayerPoints(player);

    std::ostringstream ss;
    ss << player->getName() << " has left the party.";
    broadcastPartyMessage(MESSAGE_INFO_DESCR, ss.str());

    if (missingLeader || empty()) {
        disband();
    }

    return true;
}

bool Party::passPartyLeadership(Player* player)
{
    if (!player || leader == player || player->getParty() != this) {
        return false;
    }

    //Remove it before to broadcast the message correctly
    auto it = std::find(memberList.begin(), memberList.end(), player);
    if (it != memberList.end()) {
        memberList.erase(it);
    }

    std::ostringstream ss;
    ss << player->getName() << " is now the leader of the party.";
    broadcastPartyMessage(MESSAGE_INFO_DESCR, ss.str(), true);

    Player* oldLeader = leader;
    leader = player;

    memberList.insert(memberList.begin(), oldLeader);

    updateSharedExperience();

    for (Player* member : memberList) {
        member->sendCreatureShield(oldLeader);
        member->sendCreatureShield(leader);
    }

    for (Player* invitee : inviteList) {
        invitee->sendCreatureShield(oldLeader);
        invitee->sendCreatureShield(leader);
    }

    leader->sendCreatureShield(oldLeader);
    leader->sendCreatureShield(leader);

    player->sendTextMessage(MESSAGE_INFO_DESCR, "You are now the leader of the party.");
    return true;
}

bool Party::joinParty(Player& player)
{
    if (!g_events->eventPartyOnJoin(this, &player)) {
        return false;
    }

    auto it = std::find(inviteList.begin(), inviteList.end(), &player);
    if (it == inviteList.end()) {
        return false;
    }

    inviteList.erase(it);

    std::ostringstream ss;
    ss << player.getName() << " has joined the party.";
    broadcastPartyMessage(MESSAGE_INFO_DESCR, ss.str());

    player.setParty(this);

    g_game.updatePlayerShield(&player);

    for (Player* member : memberList) {
        member->sendCreatureSkull(&player);
        player.sendPlayerPartyIcons(member);
    }

    player.sendCreatureSkull(&player);
    leader->sendCreatureSkull(&player);
    player.sendPlayerPartyIcons(leader);

    memberList.push_back(&player);

    g_game.updatePlayerHelpers(player);

    player.removePartyInvitation(this);
    updateSharedExperience();
    updateVocationsList();

    const std::string& leaderName = leader->getName();
    ss.str(std::string());
    ss << "You have joined " << leaderName << "'" << (leaderName.back() == 's' ? "" : "s") <<
       " party. Open the party channel to communicate with your companions.";
    player.sendTextMessage(MESSAGE_INFO_DESCR, ss.str());
    return true;
}

bool Party::removeInvite(Player& player, bool removeFromPlayer/* = true*/)
{
    auto it = std::find(inviteList.begin(), inviteList.end(), &player);
    if (it == inviteList.end()) {
        return false;
    }

    inviteList.erase(it);

    leader->sendCreatureShield(&player);
    player.sendCreatureShield(leader);

    if (removeFromPlayer) {
        player.removePartyInvitation(this);
    }

    if (empty()) {
        disband();
    } else {
        for (Player* member : memberList) {
            g_game.updatePlayerHelpers(*member);
        }

        g_game.updatePlayerHelpers(*leader);
    }

    return true;
}

void Party::revokeInvitation(Player& player)
{
    std::ostringstream ss;
    ss << leader->getName() << " has revoked " << (leader->getSex() == PLAYERSEX_FEMALE ? "her" : "his") << " invitation.";
    player.sendTextMessage(MESSAGE_INFO_DESCR, ss.str());

    ss.str(std::string());
    ss << "Invitation for " << player.getName() << " has been revoked.";
    leader->sendTextMessage(MESSAGE_INFO_DESCR, ss.str());

    removeInvite(player);
}

bool Party::invitePlayer(Player& player)
{
    if (isPlayerInvited(&player)) {
        return false;
    }

    std::ostringstream ss;
    ss << player.getName() << " has been invited.";

    if (memberList.empty() && inviteList.empty()) {
        ss << " Open the party channel to communicate with your members.";
        g_game.updatePlayerShield(leader);
        leader->sendCreatureSkull(leader);
    }

    leader->sendTextMessage(MESSAGE_INFO_DESCR, ss.str());

    inviteList.push_back(&player);

    for (Player* member : memberList) {
        g_game.updatePlayerHelpers(*member);
    }
    g_game.updatePlayerHelpers(*leader);

    leader->sendCreatureShield(&player);
    player.sendCreatureShield(leader);

    player.addPartyInvitation(this);

    ss.str(std::string());
    ss << leader->getName() << " has invited you to " << (leader->getSex() == PLAYERSEX_FEMALE ? "her" : "his") << " party.";
    player.sendTextMessage(MESSAGE_INFO_DESCR, ss.str());
    return true;
}

bool Party::isPlayerInvited(const Player* player) const
{
    return std::find(inviteList.begin(), inviteList.end(), player) != inviteList.end();
}

void Party::updateAllPartyIcons()
{
    for (Player* member : memberList) {
        for (Player* otherMember : memberList) {
            member->sendCreatureShield(otherMember);
        }

        member->sendCreatureShield(leader);
        leader->sendCreatureShield(member);
    }
    leader->sendCreatureShield(leader);
}

void Party::broadcastPartyMessage(MessageClasses msgClass, const std::string& msg, bool sendToInvitations /*= false*/)
{
    for (Player* member : memberList) {
        member->sendTextMessage(msgClass, msg);
    }

    leader->sendTextMessage(msgClass, msg);

    if (sendToInvitations) {
        for (Player* invitee : inviteList) {
            invitee->sendTextMessage(msgClass, msg);
        }
    }
}

void Party::broadcastPartyLoot(const std::string& loot)
{
    leader->sendTextMessage(MESSAGE_INFO_DESCR, loot);

    for (Player* member : memberList) {
        member->sendTextMessage(MESSAGE_INFO_DESCR, loot);
    }
}

void Party::updateSharedExperience()
{
    if (sharedExpActive) {
        bool result = canEnableSharedExperience();
        if (result != sharedExpEnabled) {
            sharedExpEnabled = result;
            updateAllPartyIcons();
        }
    }
}

void Party::updateVocationsList()
{
    std::set<uint32_t> vocationIds;

    uint32_t vocationId = leader->getVocation()->getFromVocation();
    if (vocationId != VOCATION_NONE) {
        vocationIds.insert(vocationId);
    }

    for (const Player* member : memberList) {
        vocationId = member->getVocation()->getFromVocation();
        if (vocationId != VOCATION_NONE) {
            vocationIds.insert(vocationId);
        }
    }

    size_t size = vocationIds.size();
    if (size > 1) {
        extraExpRate = static_cast<float>(size * (10 + (size - 1) * 5)) / 100.f;
    } else {
        extraExpRate = 0.20f;
    }
}

bool Party::setSharedExperience(Player* player, bool sharedExpActive)
{
    if (!player || leader != player) {
        return false;
    }

    if (this->sharedExpActive == sharedExpActive) {
        return true;
    }

    this->sharedExpActive = sharedExpActive;

    if (sharedExpActive) {
        this->sharedExpEnabled = canEnableSharedExperience();

        if (this->sharedExpEnabled) {
            leader->sendTextMessage(MESSAGE_INFO_DESCR, "Shared Experience is now active.");
        } else {
            leader->sendTextMessage(MESSAGE_INFO_DESCR, "Shared Experience has been activated, but some members of your party are inactive.");
        }
    } else {
        leader->sendTextMessage(MESSAGE_INFO_DESCR, "Shared Experience has been deactivated.");
    }

    updateAllPartyIcons();
    return true;
}

void Party::shareExperience(uint64_t experience, Creature* source/* = nullptr*/)
{
    uint32_t shareExperience = static_cast<uint64_t>(std::ceil(((static_cast<double>(experience) / (memberList.size() + 1)) + (static_cast<double>(experience) * extraExpRate))));
    for (Player* member : memberList) {
        member->onGainSharedExperience(shareExperience, source);
    }
    leader->onGainSharedExperience(shareExperience, source);
}

bool Party::canUseSharedExperience(const Player* player) const
{
    if (memberList.empty()) {
        return false;
    }

    uint32_t highestLevel = leader->getLevel();
    for (Player* member : memberList) {
        if (member->getLevel() > highestLevel) {
            highestLevel = member->getLevel();
        }
    }

    uint32_t minLevel = static_cast<int32_t>(std::ceil((static_cast<float>(highestLevel) * 2) / 3));
    if (player->getLevel() < minLevel) {
        return false;
    }

    if (!Position::areInRange<30, 30, 1>(leader->getPosition(), player->getPosition())) {
        return false;
    }

    if (!player->hasFlag(PlayerFlag_NotGainInFight)) {
        //check if the player has healed/attacked anything recently
        auto it = ticksMap.find(player->getID());
        if (it == ticksMap.end()) {
            return false;
        }

        uint64_t timeDiff = OTSYS_TIME() - it->second;
        if (timeDiff > static_cast<uint64_t>(g_config.getNumber(ConfigManager::PZ_LOCKED))) {
            return false;
        }
    }
    return true;
}

bool Party::canEnableSharedExperience()
{
    if (!canUseSharedExperience(leader)) {
        return false;
    }

    for (Player* member : memberList) {
        if (!canUseSharedExperience(member)) {
            return false;
        }
    }
    return true;
}

void Party::updatePlayerTicks(Player* player, uint32_t points)
{
    if (points != 0 && !player->hasFlag(PlayerFlag_NotGainInFight)) {
        ticksMap[player->getID()] = OTSYS_TIME();
        updateSharedExperience();
    }
}

void Party::clearPlayerPoints(Player* player)
{
    auto it = ticksMap.find(player->getID());
    if (it != ticksMap.end()) {
        ticksMap.erase(it);
        updateSharedExperience();
    }
}

bool Party::canOpenCorpse(uint32_t ownerId) const
{
    if (Player* player = g_game.getPlayerByID(ownerId)) {
        return leader->getID() == ownerId || player->getParty() == this;
    }
    return false;
}

Code:
/**
 * The Forgotten Server - a free and open-source MMORPG server emulator
 * Copyright (C) 2016  Mark Samman <[email protected]>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef FS_PARTY_H_41D4D7CF417C4CC99FAE94D552255044
#define FS_PARTY_H_41D4D7CF417C4CC99FAE94D552255044

#include "player.h"
#include "monsters.h"

class Player;
class Party;

typedef std::vector<Player*> PlayerVector;

class Party
{
    public:
        explicit Party(Player* leader);

        Player* getLeader() const {
            return leader;
        }
        PlayerVector& getMembers() {
            return memberList;
        }
        const PlayerVector& getInvitees() const {
            return inviteList;
        }
        size_t getMemberCount() const {
            return memberList.size();
        }
        size_t getInvitationCount() const {
            return inviteList.size();
        }

        void disband();
        bool invitePlayer(Player& player);
        bool joinParty(Player& player);
        void revokeInvitation(Player& player);
        bool passPartyLeadership(Player* player);
        bool leaveParty(Player* player);

        bool removeInvite(Player& player, bool removeFromPlayer = true);

        bool isPlayerInvited(const Player* player) const;
        void updateAllPartyIcons();
        void broadcastPartyMessage(MessageClasses msgClass, const std::string& msg, bool sendToInvitations = false);
        void broadcastPartyLoot(const std::string& loot);
        bool empty() const {
            return memberList.empty() && inviteList.empty();
        }
        bool canOpenCorpse(uint32_t ownerId) const;

        void shareExperience(uint64_t experience, Creature* source = nullptr);
        bool setSharedExperience(Player* player, bool sharedExpActive);
        bool isSharedExperienceActive() const {
            return sharedExpActive;
        }
        bool isSharedExperienceEnabled() const {
            return sharedExpEnabled;
        }
        bool canUseSharedExperience(const Player* player) const;
        void updateSharedExperience();

        void updateVocationsList();

        void updatePlayerTicks(Player* player, uint32_t points);
        void clearPlayerPoints(Player* player);

    protected:
        bool canEnableSharedExperience();

        std::map<uint32_t, int64_t> ticksMap;

        PlayerVector memberList;
        PlayerVector inviteList;

        Player* leader;

        float extraExpRate = 0.20f;

        bool sharedExpActive = false;
        bool sharedExpEnabled = false;
};

#endif
 
Last edited:
Back
Top