Implement group mentor, leadership exp sharing (SoF+ only)

Currently only works in normal groups
Some decisions: the EXP will be rounded in the favor of the group leader
No idea how live actually handles it.
This commit is contained in:
Michael Cook (mackal)
2014-10-18 00:17:46 -04:00
parent 223d06645d
commit e8eb774458
17 changed files with 131 additions and 15 deletions
+28 -4
View File
@@ -234,6 +234,7 @@ void MapOpcodes()
ConnectedOpcodes[OP_GroupInvite] = &Client::Handle_OP_GroupInvite;
ConnectedOpcodes[OP_GroupInvite2] = &Client::Handle_OP_GroupInvite2;
ConnectedOpcodes[OP_GroupMakeLeader] = &Client::Handle_OP_GroupMakeLeader;
ConnectedOpcodes[OP_GroupMentor] = &Client::Handle_OP_GroupMentor;
ConnectedOpcodes[OP_GroupRoles] = &Client::Handle_OP_GroupRoles;
ConnectedOpcodes[OP_GroupUpdate] = &Client::Handle_OP_GroupUpdate;
ConnectedOpcodes[OP_GuildBank] = &Client::Handle_OP_GuildBank;
@@ -1635,9 +1636,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
}
} //else, somebody from our group is already here...
if (group)
group->UpdatePlayer(this);
else
if (!group)
database.SetGroupID(GetName(), 0, CharacterID()); //cannot re-establish group, kill it
}
@@ -1656,9 +1655,11 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
char AssistName[64];
char PullerName[64];
char NPCMarkerName[64];
char mentoree_name[64];
int mentor_percent;
GroupLeadershipAA_Struct GLAA;
memset(ln, 0, 64);
strcpy(ln, database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, &GLAA));
strcpy(ln, database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, mentoree_name, &mentor_percent, &GLAA));
Client *c = entity_list.GetClientByName(ln);
if (c)
group->SetLeader(c);
@@ -1668,6 +1669,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
group->SetPuller(PullerName);
group->SetNPCMarker(NPCMarkerName);
group->SetGroupAAs(&GLAA);
group->SetGroupMentor(mentor_percent, mentoree_name);
//group->NotifyMainTank(this, 1);
//group->NotifyMainAssist(this, 1);
@@ -1679,6 +1681,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
group->SendLeadershipAAUpdate();
}
group->UpdatePlayer(this);
LFG = false;
}
@@ -6858,6 +6861,27 @@ void Client::Handle_OP_GroupMakeLeader(const EQApplicationPacket *app)
}
}
void Client::Handle_OP_GroupMentor(const EQApplicationPacket *app)
{
if (app->size != sizeof(GroupMentor_Struct)) {
LogFile->write(EQEMuLog::Error, "Wrong size: OP_GroupMentor, size=%i, expected %i", app->size, sizeof(GroupMentor_Struct));
DumpPacket(app);
return;
}
GroupMentor_Struct *gms = (GroupMentor_Struct *)app->pBuffer;
Group *group = GetGroup();
if (!group)
return;
gms->name[63] = '\0';
if (strlen(gms->name))
group->SetGroupMentor(gms->percent, gms->name);
else
group->ClearGroupMentor();
return;
}
void Client::Handle_OP_GroupRoles(const EQApplicationPacket *app)
{
if (app->size != sizeof(GroupRole_Struct)) {
+1
View File
@@ -138,6 +138,7 @@
void Handle_OP_GroupInvite(const EQApplicationPacket *app);
void Handle_OP_GroupInvite2(const EQApplicationPacket *app);
void Handle_OP_GroupMakeLeader(const EQApplicationPacket *app);
void Handle_OP_GroupMentor(const EQApplicationPacket *app);
void Handle_OP_GroupRoles(const EQApplicationPacket *app);
void Handle_OP_GroupUpdate(const EQApplicationPacket *app);
void Handle_OP_GuildBank(const EQApplicationPacket *app);
+14 -3
View File
@@ -133,7 +133,7 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
}
}
if(IsLeadershipEXPOn() && ((conlevel == CON_BLUE) || (conlevel == CON_WHITE) || (conlevel == CON_YELLOW) || (conlevel == CON_RED))) {
if(IsLeadershipEXPOn() && (conlevel == CON_BLUE || conlevel == CON_WHITE || conlevel == CON_YELLOW || conlevel == CON_RED)) {
add_exp = static_cast<uint32>(static_cast<float>(add_exp) * 0.8f);
if(GetGroup())
@@ -141,8 +141,19 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
if((m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel()))
&& (RuleI(Character, KillsPerGroupLeadershipAA) > 0))
{
AddLeadershipEXP(GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA), 0);
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
uint32 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA);
Client *mentoree = GetGroup()->GetMentoree();
if (GetGroup()->GetMentorPercent() && mentoree &&
mentoree->GetGroupPoints() < MaxBankedGroupLeadershipPoints(mentoree->GetLevel())) {
uint32 mentor_exp = exp * (GetGroup()->GetMentorPercent() / 100.0f);
exp -= mentor_exp;
mentoree->AddLeadershipEXP(mentor_exp, 0); // ends up rounded down
mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
}
if (exp > 0) { // possible if you mentor 100% to the other client
AddLeadershipEXP(exp, 0); // ends up rounded up if mentored, no idea how live actually does it
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
}
}
else
Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS);
+40
View File
@@ -46,6 +46,7 @@ Group::Group(uint32 gid)
: GroupIDConsumer(gid)
{
leader = nullptr;
mentoree = nullptr;
memset(members,0,sizeof(Mob*) * MAX_GROUP_MEMBERS);
AssistTargetID = 0;
TankTargetID = 0;
@@ -81,6 +82,7 @@ Group::Group(Mob* leader)
TankTargetID = 0;
PullerTargetID = 0;
memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct));
mentoree = nullptr;
uint32 i;
for(i=0;i<MAX_GROUP_MEMBERS;i++)
{
@@ -467,6 +469,11 @@ bool Group::UpdatePlayer(Mob* update){
return true;
}
}
// mentoree isn't set, the name has a length and the name is ours! update the pointer
if (update->IsClient() && !mentoree && mentoree_name.length() && !mentoree_name.compare(update->GetName()))
mentoree = update->CastToClient();
return false;
}
@@ -500,6 +507,9 @@ void Group::MemberZoned(Mob* removemob) {
if(removemob->IsClient() && HasRole(removemob, RolePuller))
SetGroupPullerTarget(0);
if (removemob->IsClient() && removemob == mentoree)
mentoree = nullptr;
}
bool Group::DelMemberOOZ(const char *Name) {
@@ -528,6 +538,8 @@ bool Group::DelMemberOOZ(const char *Name) {
}
ClearAllNPCMarks();
}
if (Name == mentoree_name)
ClearGroupMentor();
return true;
}
}
@@ -642,6 +654,9 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
UnDelegatePuller(oldmember->GetName());
}
if (oldmember->GetName() == mentoree_name)
ClearGroupMentor();
if(oldmember->IsClient())
SendMarkedNPCsToMember(oldmember->CastToClient(), true);
@@ -1736,6 +1751,31 @@ void Group::SetGroupPullerTarget(Mob *m)
}
}
void Group::SetGroupMentor(int percent, char *name)
{
mentoree_name = name;
mentor_percent = percent;
Client *client = entity_list.GetClientByName(name);
mentoree = client ? client : nullptr;
std::string query = StringFormat("UPDATE group_leaders SET mentoree = '%s', mentor_percent = %i WHERE gid = %i LIMIT 1",
mentoree_name.c_str(), mentor_percent, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group mentor: %s\n", results.ErrorMessage().c_str());
}
void Group::ClearGroupMentor()
{
mentoree_name.clear();
mentor_percent = 0;
mentoree = nullptr;
std::string query = StringFormat("UPDATE group_leaders SET mentoree = '', mentor_percent = 0 WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group mentor: %s\n", results.ErrorMessage().c_str());
}
void Group::NotifyAssistTarget(Client *c)
{
// Send a packet to the specified client notifying them of the group target selected by the Main Assist.
+8
View File
@@ -132,6 +132,11 @@ public:
const char *GetClientNameByIndex(uint8 index);
void UpdateXTargetMarkedNPC(uint32 Number, Mob *m);
void SetGroupMentor(int percent, char *name);
void ClearGroupMentor();
inline int GetMentorPercent() { return mentor_percent; }
inline Client *GetMentoree() { return mentoree; }
Mob* members[MAX_GROUP_MEMBERS];
char membername[MAX_GROUP_MEMBERS][64];
uint8 MemberRoles[MAX_GROUP_MEMBERS];
@@ -151,6 +156,9 @@ private:
uint16 PullerTargetID;
uint16 MarkedNPCs[MAX_MARKED_NPCS];
std::string mentoree_name;
Client *mentoree;
int mentor_percent;
};
#endif
+4 -1
View File
@@ -1001,9 +1001,11 @@ void WorldServer::Process() {
char AssistName[64];
char PullerName[64];
char NPCMarkerName[64];
char mentoree_name[64];
int mentor_percent;
GroupLeadershipAA_Struct GLAA;
memset(ln, 0, 64);
strcpy(ln, database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, &GLAA));
strcpy(ln, database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, mentoree_name, &mentor_percent, &GLAA));
Client *lc = entity_list.GetClientByName(ln);
if(lc)
group->SetLeader(lc);
@@ -1013,6 +1015,7 @@ void WorldServer::Process() {
group->SetPuller(PullerName);
group->SetNPCMarker(NPCMarkerName);
group->SetGroupAAs(&GLAA);
group->SetGroupMentor(mentor_percent, mentoree_name);
}
}
+1 -1
View File
@@ -2534,7 +2534,7 @@ void ZoneDatabase::RefreshGroupFromDB(Client *client){
gu->action = groupActUpdate;
strcpy(gu->yourname, client->GetName());
GetGroupLeadershipInfo(group->GetID(), gu->leadersname, nullptr, nullptr, nullptr, nullptr, &gu->leader_aas);
GetGroupLeadershipInfo(group->GetID(), gu->leadersname, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &gu->leader_aas);
gu->NPCMarkerID = group->GetNPCMarkerID();
int index = 0;