void Group::SplitExp(uint32 exp, Mob* other) { if( other->CastToNPC()->MerchantType != 0 ) // Ensure NPC isn't a merchant return; if(other->GetOwner() && other->GetOwner()->IsClient()) // Ensure owner isn't pc return; unsigned int i; int8 membercount = 0; int8 close_membercount = 0; uint8 maxlevel = 1; for (i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] != nullptr && members[i]->IsClient()) { Client *cmember = members[i]->CastToClient(); if(cmember->CastToClient()->GetZoneID() == zone->GetZoneID()) { if(members[i]->GetLevel() > maxlevel) maxlevel = members[i]->GetLevel(); if(cmember->GetLevelCon(other->GetLevel()) != CON_GREEN) { ++membercount; if(cmember->CastToClient()->IsInRange(other)) ++close_membercount; } } } } // If the NPC is green to the whole group or they are all out of the kill zone (wipe?) this will return. if (membercount <= 0 || close_membercount <= 0) return; bool isgreen = false; int conlevel = Mob::GetLevelCon(maxlevel, other->GetLevel()); if(conlevel == CON_GREEN) isgreen = true; if(isgreen && !RuleB(AlKabor, GreensGiveXPToGroup)) return; // The first loop grabs the maxlevel, so we need to adjust the count here checking for level range, // before applying xp in the third and final loop. for (i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] != nullptr && members[i]->IsClient()) // If Group Member is Client { Client *cmember = members[i]->CastToClient(); if (!cmember->IsInLevelRange(maxlevel) && cmember->CastToClient()->GetZoneID() == zone->GetZoneID() && cmember->GetLevelCon(other->GetLevel()) != CON_GREEN) { if(membercount != 0 && close_membercount != 0) { --membercount; if(cmember->CastToClient()->IsInRange(other)) --close_membercount; } else return; } } } if (membercount <= 0 || close_membercount <= 0) return; if(!RuleB(AlKabor, OutOfRangeGroupXPBonus)) membercount = close_membercount; float groupmod = 1.0; if (membercount == 2) groupmod += 0.20; else if(membercount == 3) groupmod += 0.40; if(RuleB(AlKabor, GroupEXPBonuses)) { if(membercount == 4) groupmod += 1.20; else if(membercount > 4) groupmod += 1.60; } else { if(membercount == 4) groupmod += 0.60; else if(membercount > 4) groupmod += 0.80; } uint32 groupexp = (uint32)((float)exp * groupmod * (RuleR(Character, GroupExpMultiplier))); // Give XP to all clients in the group who are close to the kill. if(!RuleB(AlKabor, Count6thGroupMember)) { // 6th member is free for division. if(close_membercount == 6) close_membercount = 5; } uint32 splitgroupxp = groupexp / close_membercount; if(splitgroupxp < 1) splitgroupxp = 1; for (i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] != nullptr && members[i]->IsClient()) // If Group Member is Client { Client *cmember = members[i]->CastToClient(); if(cmember->CastToClient()->GetZoneID() == zone->GetZoneID() && cmember->GetLevelCon(other->GetLevel()) != CON_GREEN && cmember->IsInRange(other)) { if (cmember->IsInLevelRange(maxlevel)) { if(isgreen) { // NPCs that are green to some of the group do not split XP. cmember->AddEXP(groupexp, cmember->GetLevelCon(other->GetLevel())); //_log(_GROUP__LOG, "%s gets non-split green XP worth: %i. You lucky dog.", cmember->GetName(), groupexp); } else { cmember->AddEXP(splitgroupxp, conlevel); //_log(_GROUP__LOG, "%s splits %i with the rest of the group. Their share: %i", cmember->GetName(), groupexp, splitgroupxp); //cmember->Message(CC_Yellow, "Group XP awarded is: %i Total XP is: %i for count: %i total count: %i in_exp is: %i", splitgroupxp, groupexp, close_membercount, membercount, exp); } } else Log.Out(Logs::Detail, Logs::Group, "%s is too low in level to gain XP from this group.", cmember->GetName()); } else Log.Out(Logs::Detail, Logs::Group, "%s is not in the kill zone, is out of range, or %s is green to them. They won't recieve group XP.", cmember->GetName(), other->GetCleanName()); } } }