Implement group mentoring while in raids (SoF+ only)

Note: This does not allow the raid leader to share raid leader XP
and since the raid leader doesn't gain group leadership, they can't
share that either.
This commit is contained in:
Michael Cook (mackal) 2014-10-19 17:20:07 -04:00
parent cef2aa64d9
commit a327c91bac
7 changed files with 130 additions and 12 deletions

View File

@ -3191,10 +3191,10 @@ const char* Database::GetRaidLeaderName(uint32 rid)
// maintank, assist, puller, marknpc currently unused
void Database::GetGroupLeadershipInfo(uint32 gid, uint32 rid, char *maintank,
char *assist, char *puller, char *marknpc, GroupLeadershipAA_Struct *GLAA)
char *assist, char *puller, char *marknpc, char *mentoree, int *mentor_percent, GroupLeadershipAA_Struct *GLAA)
{
std::string query = StringFormat(
"SELECT maintank, assist, puller, marknpc, leadershipaa FROM raid_leaders WHERE gid = %lu AND rid = %lu",
"SELECT maintank, assist, puller, marknpc, mentoree, mentor_percent, leadershipaa FROM raid_leaders WHERE gid = %lu AND rid = %lu",
(unsigned long)gid, (unsigned long)rid);
auto results = QueryDatabase(query);
@ -3211,6 +3211,12 @@ void Database::GetGroupLeadershipInfo(uint32 gid, uint32 rid, char *maintank,
if (marknpc)
marknpc[0] = '\0';
if (mentoree)
mentoree[0] = '\0';
if (mentor_percent)
*mentor_percent = 0;
return;
}
@ -3228,8 +3234,14 @@ void Database::GetGroupLeadershipInfo(uint32 gid, uint32 rid, char *maintank,
if (marknpc)
strcpy(marknpc, row[3]);
if (GLAA && results.LengthOfColumn(4) == sizeof(GroupLeadershipAA_Struct))
memcpy(GLAA, row[4], sizeof(GroupLeadershipAA_Struct));
if (mentoree)
strcpy(mentoree, row[4]);
if (mentor_percent)
*mentor_percent = atoi(row[5]);
if (GLAA && results.LengthOfColumn(6) == sizeof(GroupLeadershipAA_Struct))
memcpy(GLAA, row[6], sizeof(GroupLeadershipAA_Struct));
return;
}
@ -3288,7 +3300,7 @@ void Database::SetRaidGroupLeaderInfo(uint32 gid, uint32 rid)
if (results.RowsAffected() != 0)
return;
query = StringFormat("INSERT INTO raid_leaders(gid, rid, marknpc, leadershipaa, maintank, assist, puller) VALUES(%lu, %lu, '', '', '', '', '')",
query = StringFormat("INSERT INTO raid_leaders(gid, rid, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%lu, %lu, '', '', '', '', '', '', 0)",
(unsigned long)gid, (unsigned long)rid);
results = QueryDatabase(query);

View File

@ -215,7 +215,7 @@ public:
uint32 GetRaidID(const char* name);
const char *GetRaidLeaderName(uint32 rid);
void GetGroupLeadershipInfo(uint32 gid, uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr,
GroupLeadershipAA_Struct* GLAA = nullptr);
char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
void GetRaidLeadershipInfo(uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr,
RaidLeadershipAA_Struct* RLAA = nullptr);
void SetRaidGroupLeaderInfo(uint32 gid, uint32 rid);

View File

@ -0,0 +1,2 @@
ALTER TABLE `raid_leaders` ADD `mentoree` VARCHAR(64) NOT NULL;
ALTER TABLE `raid_leaders` ADD `mentor_percent` INT(4) DEFAULT 0 NOT NULL;

View File

@ -576,6 +576,7 @@ void Client::CompleteConnect()
if (grpID < 12){
raid->SendRaidGroupRemove(GetName(), grpID);
raid->SendRaidGroupAdd(GetName(), grpID);
raid->CheckGroupMentor(grpID, this);
if (raid->IsGroupLeader(GetName())) { // group leader same thing!
raid->UpdateGroupAAs(raid->GetGroup(this));
raid->GroupUpdate(grpID, false);
@ -6869,10 +6870,25 @@ void Client::Handle_OP_GroupMentor(const EQApplicationPacket *app)
return;
}
GroupMentor_Struct *gms = (GroupMentor_Struct *)app->pBuffer;
gms->name[63] = '\0';
if (IsRaidGrouped()) {
Raid *raid = GetRaid();
if (!raid)
return;
uint32 group_id = raid->GetGroup(this);
if (group_id > 11)
return;
if (strlen(gms->name))
raid->SetGroupMentor(group_id, gms->percent, gms->name);
else
raid->ClearGroupMentor(group_id);
return;
}
Group *group = GetGroup();
if (!group)
return;
gms->name[63] = '\0';
if (strlen(gms->name))
group->SetGroupMentor(gms->percent, gms->name);

View File

@ -169,9 +169,20 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
} else {
if (m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel())
&& RuleI(Character, KillsPerGroupLeadershipAA) > 0) {
// mentoring stuff needs to be added here when raids are have support for it
AddLeadershipEXP(0, GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA));
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
uint32 group_id = raid->GetGroup(this);
uint32 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA);
Client *mentoree = raid->GetMentoree(group_id);
if (raid->GetMentorPercent(group_id) && mentoree &&
mentoree->GetGroupPoints() < MaxBankedGroupLeadershipPoints(mentoree->GetLevel())) {
uint32 mentor_exp = exp * (raid->GetMentorPercent(group_id) / 100.0f);
exp -= mentor_exp;
mentoree->AddLeadershipEXP(mentor_exp, 0);
mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
}
if (exp > 0) {
AddLeadershipEXP(exp, 0);
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
}
} else {
Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS);
}

View File

@ -31,6 +31,10 @@ Raid::Raid(uint32 raidID)
memset(members ,0, (sizeof(RaidMember)*MAX_RAID_MEMBERS));
memset(&raid_aa, 0, sizeof(RaidLeadershipAA_Struct));
memset(group_aa, 0, sizeof(GroupLeadershipAA_Struct) * MAX_RAID_GROUPS);
for (int i = 0; i < MAX_RAID_GROUPS; i++) {
group_mentor[i].mentor_percent = 0;
group_mentor[i].mentoree = nullptr;
}
leader = nullptr;
memset(leadername, 0, 64);
locked = false;
@ -43,6 +47,10 @@ Raid::Raid(Client* nLeader)
memset(members ,0, (sizeof(RaidMember)*MAX_RAID_MEMBERS));
memset(&raid_aa, 0, sizeof(RaidLeadershipAA_Struct));
memset(group_aa, 0, sizeof(GroupLeadershipAA_Struct) * MAX_RAID_GROUPS);
for (int i = 0; i < MAX_RAID_GROUPS; i++) {
group_mentor[i].mentor_percent = 0;
group_mentor[i].mentoree = nullptr;
}
leader = nLeader;
memset(leadername, 0, 64);
strn0cpy(leadername, nLeader->GetName(), 64);
@ -1482,13 +1490,19 @@ void Raid::MemberZoned(Client *c)
if(!c)
return;
// Raid::GetGroup() goes over the members as well, this way we go over once
uint32 gid = RAID_GROUPLESS;
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
{
if(members[x].member == c)
{
members[x].member = nullptr;
gid = members[x].GroupNumber;
}
}
if (gid < 12 && group_mentor[gid].mentoree == c)
group_mentor[gid].mentoree = nullptr;
}
void Raid::SendHPPacketsTo(Client *c)
@ -1597,7 +1611,56 @@ void Raid::LoadLeadership()
{
database.GetRaidLeadershipInfo(GetID(), nullptr, nullptr, nullptr, nullptr, &raid_aa);
for (uint32 group_id = 0; group_id < MAX_RAID_GROUPS; group_id++)
database.GetGroupLeadershipInfo(group_id, GetID(), nullptr, nullptr, nullptr, nullptr, &group_aa[group_id]);
char mentor_name[64];
for (uint32 group_id = 0; group_id < MAX_RAID_GROUPS; group_id++) {
database.GetGroupLeadershipInfo(group_id, GetID(), nullptr, nullptr, nullptr, nullptr,
mentor_name, &group_mentor[group_id].mentor_percent, &group_aa[group_id]);
if (strlen(mentor_name)) {
group_mentor[group_id].name = mentor_name;
mentor_name[0] = '\0';
}
}
}
void Raid::SetGroupMentor(uint32 group_id, int percent, char *name)
{
if (group_id > 11)
return;
group_mentor[group_id].name = name;
group_mentor[group_id].mentor_percent = percent;
Client *client = entity_list.GetClientByName(name);
group_mentor[group_id].mentoree = client ? client : nullptr;
std::string query = StringFormat("UPDATE raid_leaders SET mentoree = '%s', mentor_percent = %i WHERE gid = %i AND rid = %i LIMIT 1",
name, percent, group_id, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set raid group mentor: %s\n", results.ErrorMessage().c_str());
}
void Raid::ClearGroupMentor(uint32 group_id)
{
if (group_id > 11)
return;
group_mentor[group_id].name.clear();
group_mentor[group_id].mentor_percent = 0;
group_mentor[group_id].mentoree = nullptr;
std::string query = StringFormat("UPDATE raid_leaders SET mentoree = '', mentor_percent = 0 WHERE gid = %i AND rid = %i LIMIT 1",
group_id, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear raid group mentor: %s\n", results.ErrorMessage().c_str());
}
// there isn't a nice place to add this in another function, unlike groups
// so we do it here instead
void Raid::CheckGroupMentor(uint32 group_id, Client *c)
{
if (!c || group_id > 11)
return;
if (group_mentor[group_id].name == c->GetName())
group_mentor[group_id].mentoree = c;
}

View File

@ -92,6 +92,12 @@ struct RaidMember{
bool IsLooter;
};
struct GroupMentor {
std::string name;
Client *mentoree;
int mentor_percent;
};
class Raid : public GroupIDConsumer {
public:
Raid(Client *nLeader);
@ -221,6 +227,12 @@ public:
inline void SetRaidAAs(RaidLeadershipAA_Struct *rlaa)
{ memcpy(&raid_aa, rlaa, sizeof(RaidLeadershipAA_Struct)); }
void SetGroupMentor(uint32 group_id, int percent, char *name);
void ClearGroupMentor(uint32 group_id);
void CheckGroupMentor(uint32 group_id, Client *c); // this just checks if we should be fixing the pointer in group mentor struct on zone
inline int GetMentorPercent(uint32 group_id) { return group_mentor[group_id].mentor_percent; }
inline Client *GetMentoree(uint32 group_id) { return group_mentor[group_id].mentoree; }
RaidMember members[MAX_RAID_MEMBERS];
char leadername[64];
protected:
@ -233,6 +245,8 @@ protected:
std::string motd;
RaidLeadershipAA_Struct raid_aa;
GroupLeadershipAA_Struct group_aa[MAX_RAID_GROUPS];
GroupMentor group_mentor[MAX_RAID_GROUPS];
};