mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-02 20:56:37 +00:00
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:
+28
-4
@@ -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)) {
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user