From ea734c90b5de9bbda696a9f88ce6031243e89531 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 12 Oct 2014 22:57:49 -0500 Subject: [PATCH 01/10] Fix for LDON Character Stat load --- changelog.txt | 3 +++ world/adventure.cpp | 1 + zone/client_packet.cpp | 1 + zone/zonedb.cpp | 28 ++++++++++++++++++++++++++++ zone/zonedb.h | 1 + 5 files changed, 34 insertions(+) diff --git a/changelog.txt b/changelog.txt index 2461b4a36..18e1a738b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 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! diff --git a/world/adventure.cpp b/world/adventure.cpp index 45dd206e5..5f61aa5e9 100644 --- a/world/adventure.cpp +++ b/world/adventure.cpp @@ -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; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 03d44c903..f7864df02 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1405,6 +1405,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */ database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */ database.LoadCharacterTribute(cid, &m_pp); /* Load CharacterTribute */ + database.LoadCharacterLDONStats(cid, &m_pp); /* Load Character LDON Stats */ /* Set item material tint */ for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 1ba36c5fd..ca6576ef9 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1028,6 +1028,34 @@ bool ZoneDatabase::LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_ return true; } +bool ZoneDatabase::LoadCharacterLDONStats(uint32 character_id, PlayerProfile_Struct* pp) { + std::string query = StringFormat("SELECT `guk_wins`, `mir_wins`, `mmc_wins`, `ruj_wins`, `tak_wins`, `guk_losses`, " + "`mir_losses`, `mmc_losses`, `ruj_losses`, `tak_losses` FROM `adventure_stats` WHERE player_id=%u", character_id); + + auto results = QueryDatabase(query); + + if (!results.Success()) + return false; + + if (results.RowCount() == 0) + return false; + + auto row = results.begin(); + + pp->ldon_wins_guk = atoi(row[0]); + pp->ldon_wins_mir = atoi(row[1]); + pp->ldon_wins_mmc = atoi(row[2]); + pp->ldon_wins_ruj = atoi(row[3]); + pp->ldon_wins_tak = atoi(row[4]); + pp->ldon_losses_guk = atoi(row[5]); + pp->ldon_losses_mir = atoi(row[6]); + pp->ldon_losses_mmc = atoi(row[7]); + pp->ldon_losses_ruj = atoi(row[8]); + pp->ldon_losses_tak = atoi(row[9]); + + return true; +} + bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp){ std::string query = StringFormat( "SELECT " diff --git a/zone/zonedb.h b/zone/zonedb.h index 30721de9a..d13e86c30 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -264,6 +264,7 @@ public: bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterLDONStats(uint32 character_id, PlayerProfile_Struct* pp); /* Character Data Saves */ bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home); From 15cec40ed586d05c7c35ffe5d584533230e4aac3 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 13 Oct 2014 15:59:11 -0700 Subject: [PATCH 02/10] Fix for issue #270, fix for temp merchant lists not loading correctly, fix for ah redundant getadventurestats code. --- common/database.cpp | 42 ++++++++++++++++++++++++++---------------- common/database.h | 3 +-- zone/client.cpp | 3 ++- zone/client_packet.cpp | 22 +++++++++++++++++----- zone/zone.cpp | 2 +- zone/zonedb.cpp | 28 ---------------------------- zone/zonedb.h | 1 - 7 files changed, 47 insertions(+), 54 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index dedc00ff1..76231c92a 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2949,11 +2949,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){ @@ -3696,8 +3705,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`, " @@ -3712,16 +3720,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; } diff --git a/common/database.h b/common/database.h index a24198ca4..68ccf003a 100644 --- a/common/database.h +++ b/common/database.h @@ -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 diff --git a/zone/client.cpp b/zone/client.cpp index a277b9858..ade40b860 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1287,7 +1287,7 @@ bool Client::UpdateLDoNPoints(int32 points, uint32 theme) m_pp.ldon_points_ruj += rujpts; m_pp.ldon_points_tak += takpts; points-=splitpts; - // if anything left, recursively loop thru again + // if anything left, recursively loop thru again if (splitpts !=0) UpdateLDoNPoints(splitpts,0); break; @@ -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; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f7864df02..e0f2b3f01 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1405,7 +1405,22 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */ database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */ database.LoadCharacterTribute(cid, &m_pp); /* Load CharacterTribute */ - database.LoadCharacterLDONStats(cid, &m_pp); /* Load Character LDON Stats */ + + /* 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++) @@ -2489,11 +2504,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; diff --git a/zone/zone.cpp b/zone/zone.cpp index 23aa95f2c..0207b28d4 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -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()) { diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ca6576ef9..1ba36c5fd 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1028,34 +1028,6 @@ bool ZoneDatabase::LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_ return true; } -bool ZoneDatabase::LoadCharacterLDONStats(uint32 character_id, PlayerProfile_Struct* pp) { - std::string query = StringFormat("SELECT `guk_wins`, `mir_wins`, `mmc_wins`, `ruj_wins`, `tak_wins`, `guk_losses`, " - "`mir_losses`, `mmc_losses`, `ruj_losses`, `tak_losses` FROM `adventure_stats` WHERE player_id=%u", character_id); - - auto results = QueryDatabase(query); - - if (!results.Success()) - return false; - - if (results.RowCount() == 0) - return false; - - auto row = results.begin(); - - pp->ldon_wins_guk = atoi(row[0]); - pp->ldon_wins_mir = atoi(row[1]); - pp->ldon_wins_mmc = atoi(row[2]); - pp->ldon_wins_ruj = atoi(row[3]); - pp->ldon_wins_tak = atoi(row[4]); - pp->ldon_losses_guk = atoi(row[5]); - pp->ldon_losses_mir = atoi(row[6]); - pp->ldon_losses_mmc = atoi(row[7]); - pp->ldon_losses_ruj = atoi(row[8]); - pp->ldon_losses_tak = atoi(row[9]); - - return true; -} - bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp){ std::string query = StringFormat( "SELECT " diff --git a/zone/zonedb.h b/zone/zonedb.h index d13e86c30..30721de9a 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -264,7 +264,6 @@ public: bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); - bool LoadCharacterLDONStats(uint32 character_id, PlayerProfile_Struct* pp); /* Character Data Saves */ bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home); From be0621de42574fe3ee208b98af12c39eeb0d3f8c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 13 Oct 2014 21:36:59 -0400 Subject: [PATCH 03/10] Partial implementation of leadership in raids Currently working: stat bonuses and client side only effects Currently not working: Mark NPC and others that need more server side work Currently only tested on UF, Ti and 62 may work, but not tested SoF, SoD, and RoF need packet translators, which are most likely the same as UF --- changelog.txt | 6 + common/database.cpp | 136 ++++++++++++++++ common/database.h | 7 + common/eq_packet_structs.h | 67 +++++++- common/patches/client62_structs.h | 58 ++++++- common/patches/rof_structs.h | 58 ++++++- common/patches/sod_structs.h | 58 ++++++- common/patches/sof_structs.h | 58 ++++++- common/patches/titanium_structs.h | 58 ++++++- common/patches/underfoot.cpp | 12 ++ common/patches/underfoot_structs.h | 68 +++++++- .../required/2014_10_13_RaidLeadership.sql | 9 ++ world/net.cpp | 1 + zone/aa.cpp | 152 ++++++++++++++++++ zone/client.cpp | 6 +- zone/client.h | 4 + zone/client_packet.cpp | 31 +++- zone/raids.cpp | 120 +++++++++++++- zone/raids.h | 24 ++- 19 files changed, 891 insertions(+), 42 deletions(-) create mode 100644 utils/sql/git/required/2014_10_13_RaidLeadership.sql diff --git a/changelog.txt b/changelog.txt index 18e1a738b..efa724859 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 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 diff --git a/common/database.cpp b/common/database.cpp index 76231c92a..5ed156ae5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -3169,6 +3169,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 diff --git a/common/database.h b/common/database.h index 68ccf003a..6fa9ef60a 100644 --- a/common/database.h +++ b/common/database.h @@ -214,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(); @@ -273,6 +279,7 @@ private: */ void ClearAllRaids(); void ClearAllRaidDetails(); + void ClearAllRaidLeaders(); }; #endif diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index eda2a5ce8..a78b2afa1 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -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 { - uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY]; + 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 { - uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY]; + 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 diff --git a/common/patches/client62_structs.h b/common/patches/client62_structs.h index 8c80e34a5..aae4c7919 100644 --- a/common/patches/client62_structs.h +++ b/common/patches/client62_structs.h @@ -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 { - uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY]; + 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 { - uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY]; + 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]; + }; }; /* diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 99dff46cc..da07840c6 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -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 { - uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY]; + 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 { - uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY]; + 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]; + }; }; /** diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 53cc148b9..c32359f76 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -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 { - uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY]; + 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 { - uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY]; + 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]; + }; }; /** diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index c943b5108..32a1e9d10 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -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 { - uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY]; + 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 { - uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY]; + 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]; + }; }; /** diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 17beb6479..e8e5a9f23 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -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 { - uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY]; + 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 { - uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY]; + 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]; + }; }; /** diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 03ef16a2a..dd31d749d 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -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; diff --git a/common/patches/underfoot_structs.h b/common/patches/underfoot_structs.h index f331d5dbc..2b7163bcf 100644 --- a/common/patches/underfoot_structs.h +++ b/common/patches/underfoot_structs.h @@ -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 { - uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY]; + 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 { - uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY]; + 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 diff --git a/utils/sql/git/required/2014_10_13_RaidLeadership.sql b/utils/sql/git/required/2014_10_13_RaidLeadership.sql new file mode 100644 index 000000000..972e09ed5 --- /dev/null +++ b/utils/sql/git/required/2014_10_13_RaidLeadership.sql @@ -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 +); diff --git a/world/net.cpp b/world/net.cpp index c7340333e..7973b5872 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -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"); diff --git a/zone/aa.cpp b/zone/aa.cpp index 8af3896d3..d07ed72cf 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -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)) diff --git a/zone/client.cpp b/zone/client.cpp index ade40b860..3b95c8d77 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -3670,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) diff --git a/zone/client.h b/zone/client.h index 3375d7066..e31c15598 100644 --- a/zone/client.h +++ b/zone/client.h @@ -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); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e0f2b3f01..e74651300 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -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); } @@ -10606,10 +10616,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(); } @@ -11228,6 +11251,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; diff --git a/zone/raids.cpp b/zone/raids.cpp index f22267a2f..0adbcdef1 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -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]); +} + diff --git a/zone/raids.h b/zone/raids.h index 44952e5da..6e2579367 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -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]; }; From d1561c28d9eabbe5162a5e9cc7a6bac3bbefc7a0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 13 Oct 2014 22:53:41 -0400 Subject: [PATCH 04/10] Raid Leadership SoF --- common/patches/sof.cpp | 12 ++++++++++++ common/patches/sof_structs.h | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index bf5046c91..2b4640f29 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -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; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 32a1e9d10..a101d3cba 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -3478,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 From 41938fbe723bd7b15e7c8ddbbe4748c7e7f91b29 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 13 Oct 2014 22:54:57 -0400 Subject: [PATCH 05/10] Raid leadership SoD --- common/patches/sod.cpp | 12 ++++++++++++ common/patches/sod_structs.h | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index edfddabca..134be8008 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -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; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index c32359f76..88c0ed91a 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -3615,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 From 6f00a69850db017853ae0c2cfa825942bbe8e3bd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 13 Oct 2014 22:55:57 -0400 Subject: [PATCH 06/10] Raid Leadership RoF --- common/patches/rof.cpp | 12 ++++++++++++ common/patches/rof_structs.h | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 49f6c51f1..96ebcaf63 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -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; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index da07840c6..e65f2b74d 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4047,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 From ef5e93b71ba9e17fd847c1fe3340509dcb0a9be9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 13 Oct 2014 23:24:25 -0400 Subject: [PATCH 07/10] Add debug log to Client::Handle_OP_DoGroupLeadershipAbility --- zone/client_packet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e74651300..fdc5e5021 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5345,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; } } From e53a91f5c3e18dbc29c76b91ce07c0e6a598dbb1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 14 Oct 2014 00:01:51 -0400 Subject: [PATCH 08/10] Added some previous unidentified (still unhandled) UF opcodes Didn't want them to get lost ;) --- utils/patches/patch_Underfoot.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utils/patches/patch_Underfoot.conf b/utils/patches/patch_Underfoot.conf index 1b65a6481..e62b24b67 100644 --- a/utils/patches/patch_Underfoot.conf +++ b/utils/patches/patch_Underfoot.conf @@ -656,3 +656,7 @@ OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs OP_InitialHPUpdate=0x0000 # OP_ItemRecastDelay=0x82d7 + +# unhandled +OP_ClearRaidNPCMarks=0x2af4 +OP_ShieldGroup=0x23a1 From c002f834d47ce459dcdcbfe044c939f7da61f8ac Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 14 Oct 2014 17:20:19 -0400 Subject: [PATCH 09/10] Correct misidentified OP_MarkNPC (RoF,SoD,SoF,UF) [skip ci] --- utils/patches/patch_RoF.conf | 4 +++- utils/patches/patch_SoD.conf | 4 +++- utils/patches/patch_SoF.conf | 4 +++- utils/patches/patch_Underfoot.conf | 5 +++-- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 16197c0da..e4eb9ba14 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -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 diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index f0d223edb..472d60e7a 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -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 diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 2e039b404..a50c1faf6 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -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 diff --git a/utils/patches/patch_Underfoot.conf b/utils/patches/patch_Underfoot.conf index e62b24b67..b7bdbc7e0 100644 --- a/utils/patches/patch_Underfoot.conf +++ b/utils/patches/patch_Underfoot.conf @@ -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 @@ -658,5 +660,4 @@ OP_InitialHPUpdate=0x0000 # OP_ItemRecastDelay=0x82d7 # unhandled -OP_ClearRaidNPCMarks=0x2af4 OP_ShieldGroup=0x23a1 From e38abaa32ac36f99ffe85cd059827acd059c9e71 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 14 Oct 2014 22:50:09 -0400 Subject: [PATCH 10/10] Optimize EntityList::UnMarkNPC Going over the group_list is much better than hitting the same group up to 5 unnecessary times --- zone/entity.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index fd031d618..4a8329639 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -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; } }