shivaria
Active Member
- Joined
- Sep 2, 2009
- Messages
- 158
- Reaction score
- 36
I am trying to make it so players can enable shared experience even when in combat. Right now you have to wait for PZ or INFIGHT and I want that to go away. I am using TFS 1.x (10.77), looking to do this in source. Heres some of my party.cpp (if the solution is there)
Code:
Party::Party(Player* leader)
{
extraExpRate = 0.20f;
sharedExpActive = false;
sharedExpEnabled = false;
this->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;
}
void Party::updateSharedExperience()
{
if (sharedExpActive) {
bool result = canEnableSharedExperience();
if (result != sharedExpEnabled) {
sharedExpEnabled = result;
updateAllPartyIcons();
}
}
}
bool Party::setSharedExperience(Player* player, bool _sharedExpActive)
{
if (!player || leader != player) {
return false;
}
if (sharedExpActive == _sharedExpActive) {
return true;
}
sharedExpActive = _sharedExpActive;
if (sharedExpActive) {
sharedExpEnabled = canEnableSharedExperience();
if (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();
}
}