Conflicts:
	changelog.txt
This commit is contained in:
Uleat 2014-10-15 19:50:35 -04:00
commit e824f81670
29 changed files with 1029 additions and 79 deletions

View File

@ -6,6 +6,15 @@ Notes: I modifed the behavior of both load and drop bots to fail on the first op
'load_bots.sql' will explicitly add bot schema, while 'drop_bots.sql' will explicitly drop it. I also added a few lines to change
a few altered tables back to their original state - as of the date in the file.
== 10/13/2014 ==
demonstar55: Partially implement leadership and raids
Currently working: client side only effects and stat bonuses.
Not working: Mark NPC, and other stuff that need extra server side support
Currently only UF tested (Tit and 62 may just work, others need packet work)
== 10/12/2014 ==
Akkadius: Fix for LDON Character Stat load
== 10/11/2014 ==
demonstar55: Implement Raid MOTD for UF
Don't forget 2014_10_11_RaidMOTD.sql!

View File

@ -2952,11 +2952,20 @@ char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf){
}
void Database::SetGroupLeaderName(uint32 gid, const char* name) {
std::string query = StringFormat("REPLACE INTO `group_leaders` SET `gid` = %lu, `leadername` = '%s'",(unsigned long)gid,name);
auto results = QueryDatabase(query);
std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", EscapeString(name).c_str(), gid);
auto result = QueryDatabase(query);
if (!results.Success())
std::cout << "Unable to set group leader: " << results.ErrorMessage() << std::endl;
if(result.RowsAffected() != 0) {
return;
}
query = StringFormat("INSERT INTO group_leaders(gid, leadername, marknpc, leadershipaa, maintank, assist, puller) VALUES(%u, '%s', '', '', '', '', '')",
gid, EscapeString(name).c_str());
result = QueryDatabase(query);
if(!result.Success()) {
LogFile->write(EQEMuLog::Debug, "Error in Database::SetGroupLeaderName: %s", result.ErrorMessage().c_str());
}
}
char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, GroupLeadershipAA_Struct* GLAA){
@ -3163,6 +3172,142 @@ const char* Database::GetRaidLeaderName(uint32 rid)
return name;
}
// maintank, assist, puller, marknpc currently unused
void Database::GetGroupLeadershipInfo(uint32 gid, uint32 rid, char *maintank,
char *assist, char *puller, char *marknpc, GroupLeadershipAA_Struct *GLAA)
{
std::string query = StringFormat(
"SELECT maintank, assist, puller, marknpc, leadershipaa FROM raid_leaders WHERE gid = %lu AND rid = %lu",
(unsigned long)gid, (unsigned long)rid);
auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount() == 0) {
if (maintank)
maintank[0] = '\0';
if (assist)
assist[0] = '\0';
if (puller)
puller[0] = '\0';
if (marknpc)
marknpc[0] = '\0';
return;
}
auto row = results.begin();
if (maintank)
strcpy(maintank, row[0]);
if (assist)
strcpy(assist, row[1]);
if (puller)
strcpy(puller, row[2]);
if (marknpc)
strcpy(marknpc, row[3]);
if (GLAA && results.LengthOfColumn(4) == sizeof(GroupLeadershipAA_Struct))
memcpy(GLAA, row[4], sizeof(GroupLeadershipAA_Struct));
return;
}
// maintank, assist, puller, marknpc currently unused
void Database::GetRaidLeadershipInfo(uint32 rid, char *maintank,
char *assist, char *puller, char *marknpc, RaidLeadershipAA_Struct *RLAA)
{
std::string query = StringFormat(
"SELECT maintank, assist, puller, marknpc, leadershipaa FROM raid_leaders WHERE gid = %lu AND rid = %lu",
(unsigned long)0xFFFFFFFF, (unsigned long)rid);
auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount() == 0) {
if (maintank)
maintank[0] = '\0';
if (assist)
assist[0] = '\0';
if (puller)
puller[0] = '\0';
if (marknpc)
marknpc[0] = '\0';
return;
}
auto row = results.begin();
if (maintank)
strcpy(maintank, row[0]);
if (assist)
strcpy(assist, row[1]);
if (puller)
strcpy(puller, row[2]);
if (marknpc)
strcpy(marknpc, row[3]);
if (RLAA && results.LengthOfColumn(4) == sizeof(RaidLeadershipAA_Struct))
memcpy(RLAA, row[4], sizeof(RaidLeadershipAA_Struct));
return;
}
void Database::SetRaidGroupLeaderInfo(uint32 gid, uint32 rid)
{
std::string query = StringFormat("UPDATE raid_leaders SET leadershipaa = '', WHERE gid = %lu AND rid = %lu",
(unsigned long)gid, (unsigned long)rid);
auto results = QueryDatabase(query);
if (results.RowsAffected() != 0)
return;
query = StringFormat("INSERT INTO raid_leaders(gid, rid, marknpc, leadershipaa, maintank, assist, puller) VALUES(%lu, %lu, '', '', '', '', '')",
(unsigned long)gid, (unsigned long)rid);
results = QueryDatabase(query);
if (!results.Success())
std::cout << "Unable to set raid/group leader: " << results.ErrorMessage() << std::endl;
return;
}
// Clearing all raid leaders
void Database::ClearAllRaidLeaders(void)
{
std::string query("DELETE from raid_leaders");
auto results = QueryDatabase(query);
if (!results.Success())
std::cout << "Unable to clear raid leaders: " << results.ErrorMessage() << std::endl;
return;
}
void Database::ClearRaidLeader(uint32 gid, uint32 rid)
{
if (rid == 0) {
ClearAllRaidLeaders();
return;
}
std::string query = StringFormat("DELETE from raid_leaders where gid = %lu and rid = %lu",
(unsigned long)gid, (unsigned long)rid);
auto results = QueryDatabase(query);
if (!results.Success())
std::cout << "Unable to clear raid leader: " << results.ErrorMessage() << std::endl;
}
bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id)
{
//we are not saved to this instance so set our instance to 0
@ -3699,8 +3844,7 @@ void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win)
QueryDatabase(query);
}
bool Database::GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, uint32 &mmc_w, uint32 &ruj_w,
uint32 &tak_w, uint32 &guk_l, uint32 &mir_l, uint32 &mmc_l, uint32 &ruj_l, uint32 &tak_l)
bool Database::GetAdventureStats(uint32 char_id, AdventureStats_Struct *as)
{
std::string query = StringFormat("SELECT `guk_wins`, `mir_wins`, `mmc_wins`, `ruj_wins`, `tak_wins`, `guk_losses`, "
@ -3715,16 +3859,18 @@ bool Database::GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, u
auto row = results.begin();
guk_w = atoi(row[0]);
mir_w = atoi(row[1]);
mmc_w = atoi(row[2]);
ruj_w = atoi(row[3]);
tak_w = atoi(row[4]);
guk_l = atoi(row[5]);
mir_l = atoi(row[6]);
mmc_l = atoi(row[7]);
ruj_l = atoi(row[8]);
tak_l = atoi(row[9]);
as->success.guk = atoi(row[0]);
as->success.mir = atoi(row[1]);
as->success.mmc = atoi(row[2]);
as->success.ruj = atoi(row[3]);
as->success.tak = atoi(row[4]);
as->failure.guk = atoi(row[5]);
as->failure.mir = atoi(row[6]);
as->failure.mmc = atoi(row[7]);
as->failure.ruj = atoi(row[8]);
as->failure.tak = atoi(row[9]);
as->failure.total = as->failure.guk + as->failure.mir + as->failure.mmc + as->failure.ruj + as->failure.tak;
as->success.total = as->success.guk + as->success.mir + as->success.mmc + as->success.ruj + as->success.tak;
return true;
}

View File

@ -174,8 +174,7 @@ public:
* Adventure related.
*/
void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win);
bool GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, uint32 &mmc_w, uint32 &ruj_w, uint32 &tak_w,
uint32 &guk_l, uint32 &mir_l, uint32 &mmc_l, uint32 &ruj_l, uint32 &tak_l);
bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as);
/*
* Account Related
@ -215,6 +214,12 @@ public:
void ClearRaidDetails(uint32 rid = 0);
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);
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);
void ClearRaidLeader(uint32 gid = 0xFFFFFFFF, uint32 rid = 0);
bool CheckDatabaseConversions();
@ -274,6 +279,7 @@ private:
*/
void ClearAllRaids();
void ClearAllRaidDetails();
void ClearAllRaidLeaders();
};
#endif

View File

@ -759,14 +759,62 @@ struct MovePotionToBelt_Struct {
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
struct LeadershipAA_Struct {
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
struct GroupLeadershipAA_Struct {
union {
struct {
uint32 groupAAMarkNPC;
uint32 groupAANPCHealth;
uint32 groupAADelegateMainAssist;
uint32 groupAADelegateMarkNPC;
uint32 groupAA4;
uint32 groupAA5;
uint32 groupAAInspectBuffs;
uint32 groupAA7;
uint32 groupAASpellAwareness;
uint32 groupAAOffenseEnhancement;
uint32 groupAAManaEnhancement;
uint32 groupAAHealthEnhancement;
uint32 groupAAHealthRegeneration;
uint32 groupAAFindPathToPC;
uint32 groupAAHealthOfTargetsTarget;
uint32 groupAA15;
};
uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY];
};
};
struct RaidLeadershipAA_Struct {
union {
struct {
uint32 raidAAMarkNPC;
uint32 raidAANPCHealth;
uint32 raidAADelegateMainAssist;
uint32 raidAADelegateMarkNPC;
uint32 raidAA4;
uint32 raidAA5;
uint32 raidAA6;
uint32 raidAASpellAwareness;
uint32 raidAAOffenseEnhancement;
uint32 raidAAManaEnhancement;
uint32 raidAAHealthEnhancement;
uint32 raidAAHealthRegeneration;
uint32 raidAAFindPathToPC;
uint32 raidAAHealthOfTargetsTarget;
uint32 raidAA14;
uint32 raidAA15;
};
uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY];
};
};
struct LeadershipAA_Struct {
union {
struct {
GroupLeadershipAA_Struct group;
RaidLeadershipAA_Struct raid;
};
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
};
/**
@ -3934,6 +3982,15 @@ struct RaidMOTD_Struct {
/*136*/ char motd[0]; // max size is 1024, but reply is variable
};
struct RaidLeadershipUpdate_Struct {
/*000*/ uint32 action;
/*004*/ char player_name[64];
/*068*/ char leader_name[64];
/*132*/ GroupLeadershipAA_Struct group; //unneeded
/*196*/ RaidLeadershipAA_Struct raid;
/*260*/ char Unknown260[128]; //unverified
};
struct RaidAdd_Struct {
/*000*/ uint32 action; //=0
/*004*/ char player_name[64]; //should both be the player's name

View File

@ -611,14 +611,62 @@ struct PotionBelt_Struct {
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
struct LeadershipAA_Struct {
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
struct GroupLeadershipAA_Struct {
union {
struct {
uint32 groupAAMarkNPC;
uint32 groupAANPCHealth;
uint32 groupAADelegateMainAssist;
uint32 groupAADelegateMarkNPC;
uint32 groupAA4;
uint32 groupAA5;
uint32 groupAAInspectBuffs;
uint32 groupAA7;
uint32 groupAASpellAwareness;
uint32 groupAAOffenseEnhancement;
uint32 groupAAManaEnhancement;
uint32 groupAAHealthEnhancement;
uint32 groupAAHealthRegeneration;
uint32 groupAAFindPathToPC;
uint32 groupAAHealthOfTargetsTarget;
uint32 groupAA15;
};
uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY];
};
};
struct RaidLeadershipAA_Struct {
union {
struct {
uint32 raidAAMarkNPC;
uint32 raidAANPCHealth;
uint32 raidAADelegateMainAssist;
uint32 raidAADelegateMarkNPC;
uint32 raidAA4;
uint32 raidAA5;
uint32 raidAA6;
uint32 raidAASpellAwareness;
uint32 raidAAOffenseEnhancement;
uint32 raidAAManaEnhancement;
uint32 raidAAHealthEnhancement;
uint32 raidAAHealthRegeneration;
uint32 raidAAFindPathToPC;
uint32 raidAAHealthOfTargetsTarget;
uint32 raidAA14;
uint32 raidAA15;
};
uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY];
};
};
struct LeadershipAA_Struct {
union {
struct {
GroupLeadershipAA_Struct group;
RaidLeadershipAA_Struct raid;
};
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
};
/*

View File

@ -2613,6 +2613,18 @@ namespace RoF
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
dest->FastQueuePacket(&outapp);
}
else if (raid_gen->action == 14)
{
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
outlaa->action = inlaa->action;
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
}
else
{
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;

View File

@ -915,14 +915,62 @@ struct PotionBelt_Struct {
BandolierItem_Struct items[MAX_POTIONS_IN_BELT];
};
struct LeadershipAA_Struct {
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
struct GroupLeadershipAA_Struct {
union {
struct {
uint32 groupAAMarkNPC;
uint32 groupAANPCHealth;
uint32 groupAADelegateMainAssist;
uint32 groupAADelegateMarkNPC;
uint32 groupAA4;
uint32 groupAA5;
uint32 groupAAInspectBuffs;
uint32 groupAA7;
uint32 groupAASpellAwareness;
uint32 groupAAOffenseEnhancement;
uint32 groupAAManaEnhancement;
uint32 groupAAHealthEnhancement;
uint32 groupAAHealthRegeneration;
uint32 groupAAFindPathToPC;
uint32 groupAAHealthOfTargetsTarget;
uint32 groupAA15;
};
uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY];
};
};
struct RaidLeadershipAA_Struct {
union {
struct {
uint32 raidAAMarkNPC;
uint32 raidAANPCHealth;
uint32 raidAADelegateMainAssist;
uint32 raidAADelegateMarkNPC;
uint32 raidAA4;
uint32 raidAA5;
uint32 raidAA6;
uint32 raidAASpellAwareness;
uint32 raidAAOffenseEnhancement;
uint32 raidAAManaEnhancement;
uint32 raidAAHealthEnhancement;
uint32 raidAAHealthRegeneration;
uint32 raidAAFindPathToPC;
uint32 raidAAHealthOfTargetsTarget;
uint32 raidAA14;
uint32 raidAA15;
};
uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY];
};
};
struct LeadershipAA_Struct {
union {
struct {
GroupLeadershipAA_Struct group;
RaidLeadershipAA_Struct raid;
};
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
};
/**
@ -3999,6 +4047,16 @@ struct RaidMOTD_Struct {
/*140*/ char motd[0]; // max size 1024, but reply is variable
};
struct RaidLeadershipUpdate_Struct {
/*000*/ uint32 action;
/*004*/ char player_name[64];
/*068*/ uint32 Unknown068;
/*072*/ char leader_name[64];
/*136*/ GroupLeadershipAA_Struct group; //unneeded
/*200*/ RaidLeadershipAA_Struct raid;
/*264*/ char Unknown264[128];
};
struct RaidAdd_Struct {
/*000*/ uint32 action; //=0
/*004*/ char player_name[64]; //should both be the player's name

View File

@ -1668,6 +1668,18 @@ namespace SoD
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
dest->FastQueuePacket(&outapp);
}
else if (raid_gen->action == 14)
{
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
outlaa->action = inlaa->action;
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
}
else
{
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;

View File

@ -711,14 +711,62 @@ struct PotionBelt_Struct {
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
struct LeadershipAA_Struct {
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
struct GroupLeadershipAA_Struct {
union {
struct {
uint32 groupAAMarkNPC;
uint32 groupAANPCHealth;
uint32 groupAADelegateMainAssist;
uint32 groupAADelegateMarkNPC;
uint32 groupAA4;
uint32 groupAA5;
uint32 groupAAInspectBuffs;
uint32 groupAA7;
uint32 groupAASpellAwareness;
uint32 groupAAOffenseEnhancement;
uint32 groupAAManaEnhancement;
uint32 groupAAHealthEnhancement;
uint32 groupAAHealthRegeneration;
uint32 groupAAFindPathToPC;
uint32 groupAAHealthOfTargetsTarget;
uint32 groupAA15;
};
uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY];
};
};
struct RaidLeadershipAA_Struct {
union {
struct {
uint32 raidAAMarkNPC;
uint32 raidAANPCHealth;
uint32 raidAADelegateMainAssist;
uint32 raidAADelegateMarkNPC;
uint32 raidAA4;
uint32 raidAA5;
uint32 raidAA6;
uint32 raidAASpellAwareness;
uint32 raidAAOffenseEnhancement;
uint32 raidAAManaEnhancement;
uint32 raidAAHealthEnhancement;
uint32 raidAAHealthRegeneration;
uint32 raidAAFindPathToPC;
uint32 raidAAHealthOfTargetsTarget;
uint32 raidAA14;
uint32 raidAA15;
};
uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY];
};
};
struct LeadershipAA_Struct {
union {
struct {
GroupLeadershipAA_Struct group;
RaidLeadershipAA_Struct raid;
};
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
};
/**
@ -3567,6 +3615,16 @@ struct RaidMOTD_Struct {
/*140*/ char motd[0]; // max size 1024, but reply is variable
};
struct RaidLeadershipUpdate_Struct {
/*000*/ uint32 action;
/*004*/ char player_name[64];
/*068*/ uint32 Unknown068;
/*072*/ char leader_name[64];
/*136*/ GroupLeadershipAA_Struct group; //unneeded
/*200*/ RaidLeadershipAA_Struct raid;
/*264*/ char Unknown264[128];
};
struct RaidAdd_Struct {
/*000*/ uint32 action; //=0
/*004*/ char player_name[64]; //should both be the player's name

View File

@ -1326,6 +1326,18 @@ namespace SoF
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
dest->FastQueuePacket(&outapp);
}
else if (raid_gen->action == 14)
{
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
outlaa->action = inlaa->action;
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
}
else
{
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;

View File

@ -689,14 +689,62 @@ struct PotionBelt_Struct {
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
struct LeadershipAA_Struct {
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
struct GroupLeadershipAA_Struct {
union {
struct {
uint32 groupAAMarkNPC;
uint32 groupAANPCHealth;
uint32 groupAADelegateMainAssist;
uint32 groupAADelegateMarkNPC;
uint32 groupAA4;
uint32 groupAA5;
uint32 groupAAInspectBuffs;
uint32 groupAA7;
uint32 groupAASpellAwareness;
uint32 groupAAOffenseEnhancement;
uint32 groupAAManaEnhancement;
uint32 groupAAHealthEnhancement;
uint32 groupAAHealthRegeneration;
uint32 groupAAFindPathToPC;
uint32 groupAAHealthOfTargetsTarget;
uint32 groupAA15;
};
uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY];
};
};
struct RaidLeadershipAA_Struct {
union {
struct {
uint32 raidAAMarkNPC;
uint32 raidAANPCHealth;
uint32 raidAADelegateMainAssist;
uint32 raidAADelegateMarkNPC;
uint32 raidAA4;
uint32 raidAA5;
uint32 raidAA6;
uint32 raidAASpellAwareness;
uint32 raidAAOffenseEnhancement;
uint32 raidAAManaEnhancement;
uint32 raidAAHealthEnhancement;
uint32 raidAAHealthRegeneration;
uint32 raidAAFindPathToPC;
uint32 raidAAHealthOfTargetsTarget;
uint32 raidAA14;
uint32 raidAA15;
};
uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY];
};
};
struct LeadershipAA_Struct {
union {
struct {
GroupLeadershipAA_Struct group;
RaidLeadershipAA_Struct raid;
};
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
};
/**
@ -3430,6 +3478,16 @@ struct RaidMOTD_Struct {
/*140*/ char motd[0]; // max size 1024, but reply is variable
};
struct RaidLeadershipUpdate_Struct {
/*000*/ uint32 action;
/*004*/ char player_name[64];
/*068*/ uint32 Unknown068;
/*072*/ char leader_name[64];
/*136*/ GroupLeadershipAA_Struct group; //unneeded
/*200*/ RaidLeadershipAA_Struct raid;
/*264*/ char Unknown264[128];
};
struct RaidAdd_Struct {
/*000*/ uint32 action; //=0
/*004*/ char player_name[64]; //should both be the player's name

View File

@ -619,14 +619,62 @@ struct PotionBelt_Struct {
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
struct LeadershipAA_Struct {
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
struct GroupLeadershipAA_Struct {
union {
struct {
uint32 groupAAMarkNPC;
uint32 groupAANPCHealth;
uint32 groupAADelegateMainAssist;
uint32 groupAADelegateMarkNPC;
uint32 groupAA4;
uint32 groupAA5;
uint32 groupAAInspectBuffs;
uint32 groupAA7;
uint32 groupAASpellAwareness;
uint32 groupAAOffenseEnhancement;
uint32 groupAAManaEnhancement;
uint32 groupAAHealthEnhancement;
uint32 groupAAHealthRegeneration;
uint32 groupAAFindPathToPC;
uint32 groupAAHealthOfTargetsTarget;
uint32 groupAA15;
};
uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY];
};
};
struct RaidLeadershipAA_Struct {
union {
struct {
uint32 raidAAMarkNPC;
uint32 raidAANPCHealth;
uint32 raidAADelegateMainAssist;
uint32 raidAADelegateMarkNPC;
uint32 raidAA4;
uint32 raidAA5;
uint32 raidAA6;
uint32 raidAASpellAwareness;
uint32 raidAAOffenseEnhancement;
uint32 raidAAManaEnhancement;
uint32 raidAAHealthEnhancement;
uint32 raidAAHealthRegeneration;
uint32 raidAAFindPathToPC;
uint32 raidAAHealthOfTargetsTarget;
uint32 raidAA14;
uint32 raidAA15;
};
uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY];
};
};
struct LeadershipAA_Struct {
union {
struct {
GroupLeadershipAA_Struct group;
RaidLeadershipAA_Struct raid;
};
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
};
/**

View File

@ -1940,6 +1940,18 @@ namespace Underfoot
strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1);
dest->FastQueuePacket(&outapp);
}
else if (raid_gen->action == 14)
{
RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer;
EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct));
structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer;
outlaa->action = inlaa->action;
strn0cpy(outlaa->player_name, inlaa->player_name, 64);
strn0cpy(outlaa->leader_name, inlaa->leader_name, 64);
memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct));
dest->FastQueuePacket(&outapp);
}
else
{
RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer;

View File

@ -754,14 +754,62 @@ struct PotionBelt_Struct {
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
struct LeadershipAA_Struct {
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
struct GroupLeadershipAA_Struct {
union {
struct {
uint32 groupAAMarkNPC;
uint32 groupAANPCHealth;
uint32 groupAADelegateMainAssist;
uint32 groupAADelegateMarkNPC;
uint32 groupAA4;
uint32 groupAA5;
uint32 groupAAInspectBuffs;
uint32 groupAA7;
uint32 groupAASpellAwareness;
uint32 groupAAOffenseEnhancement;
uint32 groupAAManaEnhancement;
uint32 groupAAHealthEnhancement;
uint32 groupAAHealthRegeneration;
uint32 groupAAFindPathToPC;
uint32 groupAAHealthOfTargetsTarget;
uint32 groupAA15;
};
uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY];
};
};
struct RaidLeadershipAA_Struct {
union {
struct {
uint32 raidAAMarkNPC;
uint32 raidAANPCHealth;
uint32 raidAADelegateMainAssist;
uint32 raidAADelegateMarkNPC;
uint32 raidAA4;
uint32 raidAA5;
uint32 raidAA6;
uint32 raidAASpellAwareness;
uint32 raidAAOffenseEnhancement;
uint32 raidAAManaEnhancement;
uint32 raidAAHealthEnhancement;
uint32 raidAAHealthRegeneration;
uint32 raidAAFindPathToPC;
uint32 raidAAHealthOfTargetsTarget;
uint32 raidAA14;
uint32 raidAA15;
};
uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY];
};
};
struct LeadershipAA_Struct {
union {
struct {
GroupLeadershipAA_Struct group;
RaidLeadershipAA_Struct raid;
};
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
};
};
/**
@ -3628,6 +3676,16 @@ struct RaidMOTD_Struct {
/*140*/ char motd[0]; // max size 1024, but reply is variable
};
struct RaidLeadershipUpdate_Struct {
/*000*/ uint32 action;
/*004*/ char player_name[64];
/*068*/ uint32 Unknown068;
/*072*/ char leader_name[64];
/*136*/ GroupLeadershipAA_Struct group; //unneeded
/*200*/ RaidLeadershipAA_Struct raid;
/*264*/ char Unknown264[128];
};
struct RaidAdd_Struct {
/*000*/ uint32 action; //=0
/*004*/ char player_name[64]; //should both be the player's name

View File

@ -289,8 +289,10 @@ OP_LeadershipExpToggle=0x3ea6
OP_LeadershipExpUpdate=0x6922
OP_PurchaseLeadershipAA=0x1962
OP_UpdateLeadershipAA=0x56aa
OP_MarkNPC=0x2d9f
OP_MarkNPC=0x1a6c
OP_MarkRaidNPC=0x2d9f #unimplemented
OP_ClearNPCMarks=0x0d2d
OP_ClearRaidNPCMarks=0x433a #unimplemented
OP_DelegateAbility=0x7820
OP_SetGroupTarget=0x118a
OP_Charm=0x7118

View File

@ -288,8 +288,10 @@ OP_LeadershipExpToggle=0x34c5 # C
OP_LeadershipExpUpdate=0x69d0 # C
OP_PurchaseLeadershipAA=0x07b3 # C
OP_UpdateLeadershipAA=0x6948 # C
OP_MarkNPC=0x0d4b # C
OP_MarkNPC=0x695c # C
OP_MarkRaidNPC=0x0d4b # C
OP_ClearNPCMarks=0x5033 # C
OP_ClearRaidNPCMarks=0x5f55 # C
OP_DoGroupLeadershipAbility=0x540b # C
OP_GroupLeadershipAAUpdate=0x0c33
OP_DelegateAbility=0x0322 # C

View File

@ -281,8 +281,10 @@ OP_LeadershipExpToggle=0x24D4 #Xinu 02/20/09
OP_LeadershipExpUpdate=0x58b6 #Derision 2009
OP_PurchaseLeadershipAA=0x1408 #Derision 2009
OP_UpdateLeadershipAA=0x7abf #Derision 2009
OP_MarkNPC=0x00c6 #Derision 2009
OP_MarkNPC=0x4697 #Derision 2009
OP_MarkRaidNPC=0x00c6
OP_ClearNPCMarks=0x2ff2 #
OP_ClearRaidNPCMarks=0x56a9 #
OP_DoGroupLeadershipAbility=0x5a64 #Derision 2009
OP_DelegateAbility=0x57e3 #Derision 2009
OP_SetGroupTarget=0x1651 #Derision 2009

View File

@ -292,8 +292,10 @@ OP_LeadershipExpToggle=0x5033 # C
OP_LeadershipExpUpdate=0x074f # C
OP_PurchaseLeadershipAA=0x5f55 # C
OP_UpdateLeadershipAA=0x77ed # C
OP_MarkNPC=0x3ec7 # C
OP_MarkNPC=0x66bf
OP_MarkRaidNPC=0x3ec7 # C
OP_ClearNPCMarks=0x5c29 # C
OP_ClearRaidNPCMarks=0x2af4
OP_DoGroupLeadershipAbility=0x0068 # C
OP_GroupLeadershipAAUpdate=0x167b # C
OP_DelegateAbility=0x6e58 # C
@ -656,3 +658,6 @@ OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs
OP_InitialHPUpdate=0x0000 #
OP_ItemRecastDelay=0x82d7
# unhandled
OP_ShieldGroup=0x23a1

View File

@ -0,0 +1,9 @@
CREATE TABLE `raid_leaders` (
`gid` int(4) unsigned NOT NULL,
`rid` int(4) unsigned NOT NULL,
`marknpc` varchar(64) NOT NULL,
`maintank` varchar(64) NOT NULL,
`assist` varchar(64) NOT NULL,
`puller` varchar(64) NOT NULL,
`leadershipaa` tinyblob NOT NULL
);

View File

@ -358,6 +358,7 @@ void Adventure::Finished(AdventureWinStatus ws)
afe.points = 0;
}
adventure_manager.AddFinishedEvent(afe);
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter).c_str()), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
}
++iter;

View File

@ -283,6 +283,7 @@ int main(int argc, char** argv) {
_log(WORLD__INIT, "Clearing raids..");
database.ClearRaid();
database.ClearRaidDetails();
database.ClearRaidLeader();
_log(WORLD__INIT, "Loading items..");
if (!database.LoadItems())
_log(WORLD__INIT_ERR, "Error: Could not load item data. But ignoring");

View File

@ -1550,6 +1550,41 @@ void Client::ResetAA(){
int Client::GroupLeadershipAAHealthEnhancement()
{
if (IsRaidGrouped()) {
int bonus = 0;
Raid *raid = GetRaid();
if (!raid)
return 0;
uint32 group_id = raid->GetGroup(this);
if (group_id < 12 && raid->GroupCount(group_id) >= 3) {
switch (raid->GetLeadershipAA(groupAAHealthEnhancement, group_id)) {
case 1:
bonus = 30;
break;
case 2:
bonus = 60;
break;
case 3:
bonus = 100;
break;
}
}
if (raid->RaidCount() >= 18) {
switch (raid->GetLeadershipAA(raidAAHealthEnhancement)) {
case 1:
bonus += 30;
break;
case 2:
bonus += 60;
break;
case 3:
bonus += 100;
break;
}
}
return bonus;
}
Group *g = GetGroup();
if(!g || (g->GroupCount() < 3))
@ -1572,6 +1607,41 @@ int Client::GroupLeadershipAAHealthEnhancement()
int Client::GroupLeadershipAAManaEnhancement()
{
if (IsRaidGrouped()) {
int bonus = 0;
Raid *raid = GetRaid();
if (!raid)
return 0;
uint32 group_id = raid->GetGroup(this);
if (group_id < 12 && raid->GroupCount(group_id) >= 3) {
switch (raid->GetLeadershipAA(groupAAManaEnhancement, group_id)) {
case 1:
bonus = 30;
break;
case 2:
bonus = 60;
break;
case 3:
bonus = 100;
break;
}
}
if (raid->RaidCount() >= 18) {
switch (raid->GetLeadershipAA(raidAAManaEnhancement)) {
case 1:
bonus += 30;
break;
case 2:
bonus += 60;
break;
case 3:
bonus += 100;
break;
}
}
return bonus;
}
Group *g = GetGroup();
if(!g || (g->GroupCount() < 3))
@ -1594,6 +1664,41 @@ int Client::GroupLeadershipAAManaEnhancement()
int Client::GroupLeadershipAAHealthRegeneration()
{
if (IsRaidGrouped()) {
int bonus = 0;
Raid *raid = GetRaid();
if (!raid)
return 0;
uint32 group_id = raid->GetGroup(this);
if (group_id < 12 && raid->GroupCount(group_id) >= 3) {
switch (raid->GetLeadershipAA(groupAAHealthRegeneration, group_id)) {
case 1:
bonus = 4;
break;
case 2:
bonus = 6;
break;
case 3:
bonus = 8;
break;
}
}
if (raid->RaidCount() >= 18) {
switch (raid->GetLeadershipAA(raidAAHealthRegeneration)) {
case 1:
bonus += 4;
break;
case 2:
bonus += 6;
break;
case 3:
bonus += 8;
break;
}
}
return bonus;
}
Group *g = GetGroup();
if(!g || (g->GroupCount() < 3))
@ -1616,6 +1721,53 @@ int Client::GroupLeadershipAAHealthRegeneration()
int Client::GroupLeadershipAAOffenseEnhancement()
{
if (IsRaidGrouped()) {
int bonus = 0;
Raid *raid = GetRaid();
if (!raid)
return 0;
uint32 group_id = raid->GetGroup(this);
if (group_id < 12 && raid->GroupCount(group_id) >= 3) {
switch (raid->GetLeadershipAA(groupAAOffenseEnhancement, group_id)) {
case 1:
bonus = 10;
break;
case 2:
bonus = 19;
break;
case 3:
bonus = 28;
break;
case 4:
bonus = 34;
break;
case 5:
bonus = 40;
break;
}
}
if (raid->RaidCount() >= 18) {
switch (raid->GetLeadershipAA(raidAAOffenseEnhancement)) {
case 1:
bonus += 10;
break;
case 2:
bonus += 19;
break;
case 3:
bonus += 28;
break;
case 4:
bonus += 34;
break;
case 5:
bonus += 40;
break;
}
}
return bonus;
}
Group *g = GetGroup();
if(!g || (g->GroupCount() < 3))

View File

@ -1344,6 +1344,7 @@ bool Client::UpdateLDoNPoints(int32 points, uint32 theme)
}
}
m_pp.ldon_points_available += points;
EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventurePointsUpdate, sizeof(AdventurePoints_Update_Struct));
AdventurePoints_Update_Struct* apus = (AdventurePoints_Update_Struct*)outapp->pBuffer;
apus->ldon_available_points = m_pp.ldon_points_available;
@ -3669,7 +3670,11 @@ void Client::LogSQL(const char *fmt, ...) {
}
void Client::GetGroupAAs(GroupLeadershipAA_Struct *into) const {
memcpy(into, &m_pp.leader_abilities, sizeof(GroupLeadershipAA_Struct));
memcpy(into, &m_pp.leader_abilities.group, sizeof(GroupLeadershipAA_Struct));
}
void Client::GetRaidAAs(RaidLeadershipAA_Struct *into) const {
memcpy(into, &m_pp.leader_abilities.raid, sizeof(RaidLeadershipAA_Struct));
}
void Client::EnteringMessages(Client* client)

View File

@ -559,6 +559,9 @@ public:
void SendLeadershipEXPUpdate();
bool IsLeadershipEXPOn();
inline int GetLeadershipAA(int AAID) { return m_pp.leader_abilities.ranks[AAID]; }
inline LeadershipAA_Struct &GetLeadershipAA() { return m_pp.leader_abilities; }
inline GroupLeadershipAA_Struct &GetGroupLeadershipAA() { return m_pp.leader_abilities.group; }
inline RaidLeadershipAA_Struct &GetRaidLeadershipAA() { return m_pp.leader_abilities.raid; }
int GroupLeadershipAAHealthEnhancement();
int GroupLeadershipAAManaEnhancement();
int GroupLeadershipAAHealthRegeneration();
@ -585,6 +588,7 @@ public:
bool CheckLoreConflict(const Item_Struct* item);
void ChangeLastName(const char* in_lastname);
void GetGroupAAs(GroupLeadershipAA_Struct *into) const;
void GetRaidAAs(RaidLeadershipAA_Struct *into) const;
void ClearGroupAAs();
void UpdateGroupAAs(int32 points, uint32 type);
void SacrificeConfirm(Client* caster);

View File

@ -546,6 +546,7 @@ void Client::CompleteConnect()
raid = new Raid(raidid);
if (raid->GetID() != 0){
entity_list.AddRaid(raid, raidid);
raid->LoadLeadership(); // Recreating raid in new zone, get leadership from DB
}
else
raid = nullptr;
@ -566,11 +567,20 @@ void Client::CompleteConnect()
raid->SendBulkRaid(this);
raid->SendGroupUpdate(this);
raid->SendRaidMOTD(this);
if (raid->IsLeader(this)) { // We're a raid leader, lets update just in case!
raid->UpdateRaidAAs();
raid->SendAllRaidLeadershipAA();
}
uint32 grpID = raid->GetGroup(GetName());
if (grpID < 12){
raid->SendRaidGroupRemove(GetName(), grpID);
raid->SendRaidGroupAdd(GetName(), grpID);
if (raid->IsGroupLeader(GetName())) { // group leader same thing!
raid->UpdateGroupAAs(raid->GetGroup(this));
raid->GroupUpdate(grpID, false);
}
}
raid->SendGroupLeadershipAA(this, grpID); // this may get sent an extra time ...
if (raid->IsLocked())
raid->SendRaidLockTo(this);
}
@ -1406,6 +1416,22 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */
database.LoadCharacterTribute(cid, &m_pp); /* Load CharacterTribute */
/* Load AdventureStats */
AdventureStats_Struct as;
if(database.GetAdventureStats(cid, &as))
{
m_pp.ldon_wins_guk = as.success.guk;
m_pp.ldon_wins_mir = as.success.mir;
m_pp.ldon_wins_mmc = as.success.mmc;
m_pp.ldon_wins_ruj = as.success.ruj;
m_pp.ldon_wins_tak = as.success.tak;
m_pp.ldon_losses_guk = as.failure.guk;
m_pp.ldon_losses_mir = as.failure.mir;
m_pp.ldon_losses_mmc = as.failure.mmc;
m_pp.ldon_losses_ruj = as.failure.ruj;
m_pp.ldon_losses_tak = as.failure.tak;
}
/* Set item material tint */
for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++)
if (m_pp.item_tint[i].rgb.use_tint == 1 || m_pp.item_tint[i].rgb.use_tint == 255)
@ -2488,11 +2514,8 @@ void Client::Handle_OP_AdventureStatsRequest(const EQApplicationPacket *app)
EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureStatsReply, sizeof(AdventureStats_Struct));
AdventureStats_Struct *as = (AdventureStats_Struct*)outapp->pBuffer;
if (database.GetAdventureStats(CharacterID(), as->success.guk, as->success.mir, as->success.mmc, as->success.ruj,
as->success.tak, as->failure.guk, as->failure.mir, as->failure.mmc, as->failure.ruj, as->failure.tak))
if (database.GetAdventureStats(CharacterID(), as))
{
as->failure.total = as->failure.guk + as->failure.mir + as->failure.mmc + as->failure.ruj + as->failure.tak;
as->success.total = as->success.guk + as->success.mir + as->success.mmc + as->success.ruj + as->success.tak;
m_pp.ldon_wins_guk = as->success.guk;
m_pp.ldon_wins_mir = as->success.mir;
m_pp.ldon_wins_mmc = as->success.mmc;
@ -5322,6 +5345,8 @@ void Client::Handle_OP_DoGroupLeadershipAbility(const EQApplicationPacket *app)
}
default:
LogFile->write(EQEMuLog::Debug, "Got unhandled OP_DoGroupLeadershipAbility Ability: %d Parameter: %d",
dglas->Ability, dglas->Parameter);
break;
}
}
@ -10593,10 +10618,23 @@ void Client::Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app)
u->pointsleft = m_pp.group_leadership_points;
FastQueuePacket(&outapp);
Group *g = GetGroup();
// Update all group members with the new AA the leader has purchased.
if (g) {
if (IsRaidGrouped()) {
Raid *r = GetRaid();
if (!r)
return;
if (aaid >= raidAAMarkNPC) {
r->UpdateRaidAAs();
r->SendAllRaidLeadershipAA();
} else {
uint32 gid = r->GetGroup(this);
r->UpdateGroupAAs(gid);
r->GroupUpdate(gid, false);
}
} else if (IsGrouped()) {
Group *g = GetGroup();
if (!g)
return;
g->UpdateGroupAAs();
g->SendLeadershipAAUpdate();
}
@ -11215,6 +11253,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
{
if (strcmp(r->leadername, GetName()) == 0){
r->SetRaidLeader(GetName(), ri->leader_name);
r->UpdateRaidAAs();
r->SendAllRaidLeadershipAA();
}
}
break;

View File

@ -4120,15 +4120,10 @@ void EntityList::UnMarkNPC(uint16 ID)
// each group to remove the dead mobs entity ID from the groups list of NPCs marked via the
// Group Leadership AA Mark NPC ability.
//
auto it = client_list.begin();
while (it != client_list.end()) {
if (it->second) {
Group *g = nullptr;
g = it->second->GetGroup();
if (g)
g->UnMarkNPC(ID);
}
auto it = group_list.begin();
while (it != group_list.end()) {
if (*it)
(*it)->UnMarkNPC(ID);
++it;
}
}

View File

@ -29,6 +29,8 @@ Raid::Raid(uint32 raidID)
: GroupIDConsumer(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);
leader = nullptr;
memset(leadername, 0, 64);
locked = false;
@ -39,6 +41,8 @@ Raid::Raid(Client* nLeader)
: GroupIDConsumer()
{
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);
leader = nLeader;
memset(leadername, 0, 64);
strn0cpy(leadername, nLeader->GetName(), 64);
@ -84,8 +88,18 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo
LearnMembers();
VerifyRaid();
if (rleader) {
database.SetRaidGroupLeaderInfo(RAID_GROUPLESS, GetID());
UpdateRaidAAs();
}
if (group != RAID_GROUPLESS && groupleader) {
database.SetRaidGroupLeaderInfo(group, GetID());
UpdateGroupAAs(group);
}
if(group < 12)
GroupUpdate(group);
else // get raid AAs, GroupUpdate will handles it otherwise
SendGroupLeadershipAA(c, RAID_GROUPLESS);
SendRaidAddAll(c->GetName());
c->SetRaidGrouped(true);
@ -186,6 +200,18 @@ void Raid::SetGroupLeader(const char *who, bool glFlag)
safe_delete(pack);
}
Client *Raid::GetGroupLeader(uint32 group_id)
{
if (group_id == RAID_GROUPLESS)
return nullptr;
for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++)
if (members[i].member && members[i].IsGroupLeader && members[i].GroupNumber == group_id)
return members[i].member;
return nullptr;
}
void Raid::SetRaidLeader(const char *wasLead, const char *name)
{
std::string query = StringFormat("UPDATE raid_members SET israidleader = 0 WHERE name = '%s'", wasLead);
@ -218,6 +244,59 @@ void Raid::SetRaidLeader(const char *wasLead, const char *name)
safe_delete(pack);
}
void Raid::SaveGroupLeaderAA(uint32 gid)
{
char *queryBuffer = new char[sizeof(GroupLeadershipAA_Struct) * 2 + 1];
database.DoEscapeString(queryBuffer, (char*)&group_aa[gid], sizeof(GroupLeadershipAA_Struct));
std::string query = "UPDATE raid_leaders SET leadershipaa = '";
query += queryBuffer;
query += StringFormat("' WHERE gid = %lu AND rid = %lu LIMIT 1", gid, GetID());
safe_delete_array(queryBuffer);
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
}
void Raid::SaveRaidLeaderAA()
{
char *queryBuffer = new char[sizeof(RaidLeadershipAA_Struct) * 2 + 1];
database.DoEscapeString(queryBuffer, (char*)&raid_aa, sizeof(RaidLeadershipAA_Struct));
_hex(NET__ERROR, queryBuffer, sizeof(RaidLeadershipAA_Struct));
std::string query = "UPDATE raid_leaders SET leadershipaa = '";
query += queryBuffer;
query += StringFormat("' WHERE gid = %lu AND rid = %lu LIMIT 1", RAID_GROUPLESS, GetID());
safe_delete_array(queryBuffer);
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
}
void Raid::UpdateGroupAAs(uint32 gid)
{
Client *gl = GetGroupLeader(gid);
if (gl)
gl->GetGroupAAs(&group_aa[gid]);
else
memset(&group_aa[gid], 0, sizeof(GroupLeadershipAA_Struct));
SaveGroupLeaderAA(gid);
}
void Raid::UpdateRaidAAs()
{
Client *rl = GetLeader();
if (rl)
rl->GetRaidAAs(&raid_aa);
else
memset(&raid_aa, 0, sizeof(RaidLeadershipAA_Struct));
SaveRaidLeaderAA();
}
bool Raid::IsGroupLeader(const char *who)
{
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
@ -1094,6 +1173,7 @@ void Raid::SendGroupUpdate(Client *to)
strn0cpy(gu->leadersname, to->GetName(), 64);
}
strn0cpy(gu->yourname, to->GetName(), 64);
memcpy(&gu->leader_aas, &group_aa[grp], sizeof(GroupLeadershipAA_Struct));
to->FastQueuePacket(&outapp);
}
@ -1106,8 +1186,10 @@ void Raid::GroupUpdate(uint32 gid, bool initial)
{
if(strlen(members[x].membername) > 0){
if(members[x].GroupNumber == gid){
if(members[x].member)
if(members[x].member) {
SendGroupUpdate(members[x].member);
SendGroupLeadershipAA(members[x].member, gid);
}
}
}
}
@ -1244,6 +1326,34 @@ void Raid::SendRaidMOTDToWorld()
safe_delete(pack);
}
void Raid::SendGroupLeadershipAA(Client *c, uint32 gid)
{
EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct));
RaidLeadershipUpdate_Struct *rlaa = (RaidLeadershipUpdate_Struct *)outapp->pBuffer;
rlaa->action = raidSetLeaderAbilities;
strn0cpy(rlaa->leader_name, c->GetName(), 64);
strn0cpy(rlaa->player_name, c->GetName(), 64);
if (gid != RAID_GROUPLESS)
memcpy(&rlaa->group, &group_aa[gid], sizeof(GroupLeadershipAA_Struct));
memcpy(&rlaa->raid, &raid_aa, sizeof(RaidLeadershipAA_Struct));
c->QueuePacket(outapp);
safe_delete(outapp);
}
void Raid::SendGroupLeadershipAA(uint32 gid)
{
for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++)
if (members[i].member && members[i].GroupNumber == gid)
SendGroupLeadershipAA(members[i].member, gid);
}
void Raid::SendAllRaidLeadershipAA()
{
for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++)
if (members[i].member)
SendGroupLeadershipAA(members[i].member, members[i].GroupNumber);
}
void Raid::LockRaid(bool lockFlag)
{
std::string query = StringFormat("UPDATE raid_details SET locked = %d WHERE raidid = %lu",
@ -1484,3 +1594,11 @@ void Raid::RaidMessage_StringID(Mob* sender, uint32 type, uint32 string_id, cons
}
}
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]);
}

View File

@ -43,8 +43,8 @@ enum { //raid packet types:
raidChangeLootType = 11,
raidStringID = 12,
raidChangeGroupLeader = 13, //136 raid leader, new group leader, group_id?
raidBecomeGroupLeader = 14, //472
raidUnknown2 = 15,
raidSetLeaderAbilities = 14, //472
raidSetLeaderData = 15, // 14,15 SoE names, not sure on difference, 14 packet has 0x100 bytes 15 0x214 in addition to raid general
raidChangeGroup = 16, //?? len 136 old leader, new leader, 0 (preceeded with a remove2)
raidLock = 17, //len 136 leader?, leader, 0
raidUnlock = 18, //len 136 leader?, leader, 0
@ -79,6 +79,7 @@ enum { //raid command types
#define MAX_RAID_GROUPS 12
#define MAX_RAID_MEMBERS 72
const uint32 RAID_GROUPLESS = 0xFFFFFFFF;
struct RaidMember{
char membername[64];
@ -111,6 +112,7 @@ public:
void DisbandRaid();
void MoveMember(const char *name, uint32 newGroup);
void SetGroupLeader(const char *who, bool glFlag = true);
Client *GetGroupLeader(uint32 group_id);
void RemoveGroupLeader(const char *who);
bool IsGroupLeader(const char *who);
bool IsRaidMember(const char *name);
@ -203,6 +205,22 @@ public:
void QueuePacket(const EQApplicationPacket *app, bool ack_req = true);
// Leadership
void UpdateGroupAAs(uint32 gid);
void SaveGroupLeaderAA(uint32 gid);
void UpdateRaidAAs();
void SaveRaidLeaderAA();
void SendGroupLeadershipAA(Client *c, uint32 gid);
void SendGroupLeadershipAA(uint32 gid);
void SendAllRaidLeadershipAA();
void LoadLeadership();
inline int GetLeadershipAA(int AAID, uint32 gid = 0)
{ if (AAID >= 16) return raid_aa.ranks[AAID - 16]; else return group_aa[gid].ranks[AAID]; }
inline void SetGroupAAs(uint32 gid, GroupLeadershipAA_Struct *glaa)
{ memcpy(&group_aa[gid], glaa, sizeof(GroupLeadershipAA_Struct)); }
inline void SetRaidAAs(RaidLeadershipAA_Struct *rlaa)
{ memcpy(&raid_aa, rlaa, sizeof(RaidLeadershipAA_Struct)); }
RaidMember members[MAX_RAID_MEMBERS];
char leadername[64];
protected:
@ -213,6 +231,8 @@ protected:
bool disbandCheck;
bool forceDisband;
std::string motd;
RaidLeadershipAA_Struct raid_aa;
GroupLeadershipAA_Struct group_aa[MAX_RAID_GROUPS];
};

View File

@ -411,7 +411,7 @@ void Zone::LoadTempMerchantData() {
"WHERE "
"ml.npcid = se.npcid "
"AND se.spawngroupid = s2.spawngroupid "
"AND s2.zone = '%s' AND s2.version = %i"
"AND s2.zone = '%s' AND s2.version = %i "
"ORDER BY ml.slot ", GetShortName(), GetInstanceVersion());
auto results = database.QueryDatabase(query);
if (!results.Success()) {