From b3d8e22539b1a9bc97e9f5bc211a7649d85c8616 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 2 Oct 2014 22:52:25 -0400 Subject: [PATCH 01/10] Make ZoneDatabase::FillAAEffects get the data from memory Note: This should probably be moved out of ZoneDatabase --- zone/aa.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 1f933b30e..8af3896d3 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1751,19 +1751,15 @@ void ZoneDatabase::FillAAEffects(SendAA_Struct* aa_struct){ if(!aa_struct) return; - std::string query = StringFormat("SELECT effectid, base1, base2, slot from aa_effects where aaid=%i order by slot asc", aa_struct->id); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogFile->write(EQEMuLog::Error, "Error in Client::FillAAEffects query: '%s': %s", query.c_str(), results.ErrorMessage().c_str()); - return; - } - - int index = 0; - for (auto row = results.begin(); row != results.end(); ++row, ++index) { - aa_struct->abilities[index].skill_id=atoi(row[0]); - aa_struct->abilities[index].base1=atoi(row[1]); - aa_struct->abilities[index].base2=atoi(row[2]); - aa_struct->abilities[index].slot=atoi(row[3]); + auto it = aa_effects.find(aa_struct->id); + if (it != aa_effects.end()) { + for (int slot = 0; slot < aa_struct->total_abilities; slot++) { + // aa_effects is a map of a map, so the slot reference does not start at 0 + aa_struct->abilities[slot].skill_id = it->second[slot + 1].skill_id; + aa_struct->abilities[slot].base1 = it->second[slot + 1].base1; + aa_struct->abilities[slot].base2 = it->second[slot + 1].base2; + aa_struct->abilities[slot].slot = it->second[slot + 1].slot; + } } } From 0438dee22e125d53e0edb2c270151d5f505bf2de Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 3 Oct 2014 01:37:51 -0400 Subject: [PATCH 02/10] Rework ZoneDatabase::SavePetInfo -- should be better Worst case before some something like 96 queries. --- zone/zonedb.cpp | 136 ++++++++++++++++++++---------------------------- 1 file changed, 57 insertions(+), 79 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index b49837704..7815b5b96 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2895,96 +2895,74 @@ void ZoneDatabase::LoadBuffs(Client *client) { } } -void ZoneDatabase::SavePetInfo(Client *client) { +void ZoneDatabase::SavePetInfo(Client *client) +{ + PetInfo *petinfo = nullptr; - PetInfo *petinfo = client->GetPetInfo(0); - PetInfo *suspended = client->GetPetInfo(1); - - std::string query = StringFormat("DELETE FROM `character_pet_buffs` WHERE `char_id` = %u", client->CharacterID()); - auto results = database.QueryDatabase(query); - if(!results.Success()) + std::string query = StringFormat("DELETE FROM `character_pet_buffs` WHERE `char_id` = %u", client->CharacterID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) return; - query = StringFormat("DELETE FROM `character_pet_buffs` WHERE `char_id` = %u", client->CharacterID()); + query = StringFormat("DELETE FROM `character_pet_inventory` WHERE `char_id` = %u", client->CharacterID()); results = database.QueryDatabase(query); - if(!results.Success()) + if (!results.Success()) return; - query = StringFormat("INSERT INTO `character_pet_info` " - "(`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) " - "VALUES (%u, 0, '%s', %i, %u, %u, %u, %f) " - "ON DUPLICATE KEY UPDATE `petname` = '%s', `petpower` = %i, `spell_id` = %u, " - "`hp` = %u, `mana` = %u, `size` = %f", - client->CharacterID(), petinfo->Name, petinfo->petpower, petinfo->SpellID, - petinfo->HP, petinfo->Mana, petinfo->size, petinfo->Name, petinfo->petpower, - petinfo->SpellID, petinfo->HP, petinfo->Mana, petinfo->size); - results = database.QueryDatabase(query); - if(!results.Success()) - return; + for (int pet = 0; pet < 2; pet++) { + petinfo = client->GetPetInfo(pet); + if (!petinfo) + continue; - for(int index = 0; index < RuleI(Spells, MaxTotalSlotsPET); index++) { - if (petinfo->Buffs[index].spellid == SPELL_UNKNOWN || petinfo->Buffs[index].spellid == 0) - continue; + query = StringFormat("INSERT INTO `character_pet_info` " + "(`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) " + "VALUES (%u, %u, '%s', %i, %u, %u, %u, %f) " + "ON DUPLICATE KEY UPDATE `petname` = '%s', `petpower` = %i, `spell_id` = %u, " + "`hp` = %u, `mana` = %u, `size` = %f", + client->CharacterID(), pet, petinfo->Name, petinfo->petpower, petinfo->SpellID, + petinfo->HP, petinfo->Mana, petinfo->size, // and now the ON DUPLICATE ENTRIES + petinfo->Name, petinfo->petpower, petinfo->SpellID, petinfo->HP, petinfo->Mana, petinfo->size); + results = database.QueryDatabase(query); + if (!results.Success()) + return; + query.clear(); - query = StringFormat("INSERT INTO `character_pet_buffs` " - "(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " - "`ticsremaining`, `counters`) " - "VALUES (%u, 0, %u, %u, %u, %u, %d)", - client->CharacterID(), index, petinfo->Buffs[index].spellid, - petinfo->Buffs[index].level, petinfo->Buffs[index].duration, - petinfo->Buffs[index].counters); - database.QueryDatabase(query); - } + // pet buffs! + for (int index = 0; index < RuleI(Spells, MaxTotalSlotsPET); index++) { + if (petinfo->Buffs[index].spellid == SPELL_UNKNOWN || petinfo->Buffs[index].spellid == 0) + continue; + if (query.length() == 0) + query = StringFormat("INSERT INTO `character_pet_buffs` " + "(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " + "`ticsremaining`, `counters`) " + "VALUES (%u, %u, %u, %u, %u, %u, %d)", + client->CharacterID(), pet, index, petinfo->Buffs[index].spellid, + petinfo->Buffs[index].level, petinfo->Buffs[index].duration, + petinfo->Buffs[index].counters); + else + query += StringFormat(", (%u, %u, %u, %u, %u, %u, %d)", + client->CharacterID(), pet, index, petinfo->Buffs[index].spellid, + petinfo->Buffs[index].level, petinfo->Buffs[index].duration, + petinfo->Buffs[index].counters); + } + database.QueryDatabase(query); + query.clear(); - for(int index = 0; index < RuleI(Spells, MaxTotalSlotsPET); index++) { - if (petinfo->Buffs[index].spellid == SPELL_UNKNOWN || petinfo->Buffs[index].spellid == 0) - continue; + // pet inventory! + for (int index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; index++) { + if (!petinfo->Items[index]) + continue; - query = StringFormat("INSERT INTO `character_pet_buffs` " - "(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " - "`ticsremaining`, `counters`) " - "VALUES (%u, 1, %u, %u, %u, %u, %d)", - client->CharacterID(), index, suspended->Buffs[index].spellid, - suspended->Buffs[index].level, suspended->Buffs[index].duration, - suspended->Buffs[index].counters); - database.QueryDatabase(query); + if (query.length() == 0) + query = StringFormat("INSERT INTO `character_pet_inventory` " + "(`char_id`, `pet`, `slot`, `item_id`) " + "VALUES (%u, %u, %u, %u)", + client->CharacterID(), pet, index, petinfo->Items[index]); + else + query += StringFormat(", (%u, %u, %u, %u)", client->CharacterID(), pet, index, petinfo->Items[index]); + } + database.QueryDatabase(query); } - - for (int index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; index++) { - if(!petinfo->Items[index]) - continue; - - query = StringFormat("INSERT INTO `character_pet_inventory` " - "(`char_id`, `pet`, `slot`, `item_id`) " - "VALUES (%u, 0, %u, %u)", - client->CharacterID(), index, petinfo->Items[index]); - database.QueryDatabase(query); - } - - query = StringFormat("INSERT INTO `character_pet_info` " - "(`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) " - "VALUES (%u, 1, '%s', %u, %u, %u, %u, %f) " - "ON DUPLICATE KEY UPDATE " - "`petname`='%s', `petpower`=%i, `spell_id`=%u, `hp`=%u, `mana`=%u, `size`=%f", - client->CharacterID(), suspended->Name, suspended->petpower, suspended->SpellID, - suspended->HP, suspended->Mana, suspended->size, suspended->Name, suspended->petpower, - suspended->SpellID, suspended->HP, suspended->Mana, suspended->size); - results = database.QueryDatabase(query); - if(!results.Success()) - return; - - - for (int index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; index++) { - if(!suspended->Items[index]) - continue; - - query = StringFormat("INSERT INTO `character_pet_inventory` " - "(`char_id`, `pet`, `slot`, `item_id`) " - "VALUES (%u, 1, %u, %u)", - client->CharacterID(), index, suspended->Items[index]); - database.QueryDatabase(query); - } - } void ZoneDatabase::RemoveTempFactions(Client *client) { From bb2bed7b00dc17e55516c9d412a534b5c8861eca Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 3 Oct 2014 02:03:48 -0400 Subject: [PATCH 03/10] Fixed OP_AugmentInfo packet processing that I broked'd --- changelog.txt | 3 +++ common/eq_packet_structs.h | 6 +++--- common/patches/client62.cpp | 5 ----- common/patches/client62_ops.h | 1 - common/patches/client62_structs.h | 5 ----- common/patches/rof_structs.h | 6 +++--- common/patches/sod_structs.h | 6 +++--- common/patches/sof_structs.h | 6 +++--- common/patches/titanium.cpp | 3 --- common/patches/titanium_ops.h | 1 - common/patches/underfoot_structs.h | 6 +++--- 11 files changed, 18 insertions(+), 30 deletions(-) diff --git a/changelog.txt b/changelog.txt index 81233fcd7..b31afa449 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/03/2014 == +Uleat: Fixed Ti(6.2) OP_AugmentInfo translation that I broke (does not currently need and I mis-read a process) + == 10/02/2014 == Uleat: First round of Ti/6.2 translators added - needed for re-enumeration diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 47516b24a..8e5588e5c 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4312,9 +4312,9 @@ struct ControlBoat_Struct { struct AugmentInfo_Struct { -/*000*/ uint32 itemid; // id of the solvent needed -/*004*/ uint8 window; // window to display the information in -/*005*/ uint8 unknown005[67]; // total packet length 72, all the rest were always 00 +/*000*/ uint32 itemid; // id of the solvent needed +/*004*/ uint8 window; // window to display the information in +/*005*/ uint8 unknown005[67]; // total packet length 72, all the rest were always 00 /*072*/ }; diff --git a/common/patches/client62.cpp b/common/patches/client62.cpp index bbc8757d0..d9def3dbb 100644 --- a/common/patches/client62.cpp +++ b/common/patches/client62.cpp @@ -990,11 +990,6 @@ namespace Client62 FINISH_DIRECT_DECODE(); } -#if 0 - // needs to be tested (and OpCode found) - DECODE(OP_AugmentInfo) { DECODE_FORWARD(OP_ReadBook); } -#endif - DECODE(OP_AugmentItem) { DECODE_LENGTH_EXACT(structs::AugmentItem_Struct); diff --git a/common/patches/client62_ops.h b/common/patches/client62_ops.h index 0ff0cdaa7..eb7ff2205 100644 --- a/common/patches/client62_ops.h +++ b/common/patches/client62_ops.h @@ -34,7 +34,6 @@ E(OP_ZoneSpawns) // incoming packets that require a DECODE translation: D(OP_AdventureMerchantSell) D(OP_ApplyPoison) -//D(OP_AugmentInfo) - needs opcode for conf file update D(OP_AugmentItem) D(OP_CastSpell) D(OP_CharacterCreate) diff --git a/common/patches/client62_structs.h b/common/patches/client62_structs.h index 70f05859e..24e273682 100644 --- a/common/patches/client62_structs.h +++ b/common/patches/client62_structs.h @@ -3099,11 +3099,6 @@ struct GuildMemberUpdate_Struct { /*72*/ uint32 unknown072; }; - - - - - }; //end namespace structs }; //end namespace Client62 diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 9cec4f5fa..0549b4b58 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4585,9 +4585,9 @@ struct ItemQuaternaryBodyStruct struct AugmentInfo_Struct { -/*000*/ uint32 itemid; // id of the solvent needed -/*004*/ uint8 window; // window to display the information in -/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00 +/*000*/ uint32 itemid; // id of the solvent needed +/*004*/ uint8 window; // window to display the information in +/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00 /*076*/ }; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index ea4726a62..64d907c5b 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -4109,9 +4109,9 @@ struct ItemQuaternaryBodyStruct struct AugmentInfo_Struct { -/*000*/ uint32 itemid; // id of the solvent needed -/*004*/ uint8 window; // window to display the information in -/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00 +/*000*/ uint32 itemid; // id of the solvent needed +/*004*/ uint8 window; // window to display the information in +/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00 /*076*/ }; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 0beb17db6..5164af3eb 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -3963,9 +3963,9 @@ struct ItemQuaternaryBodyStruct struct AugmentInfo_Struct { -/*000*/ uint32 itemid; // id of the solvent needed -/*004*/ uint8 window; // window to display the information in -/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00 +/*000*/ uint32 itemid; // id of the solvent needed +/*004*/ uint8 window; // window to display the information in +/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00 /*076*/ }; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 92695f7a1..d0235049d 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1347,9 +1347,6 @@ namespace Titanium FINISH_DIRECT_DECODE(); } - // needs to be tested - DECODE(OP_AugmentInfo) { DECODE_FORWARD(OP_ReadBook); } - DECODE(OP_AugmentItem) { DECODE_LENGTH_EXACT(structs::AugmentItem_Struct); diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index 2aa3d8071..338558602 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -47,7 +47,6 @@ E(OP_ZoneSpawns) // incoming packets that require a DECODE translation: D(OP_AdventureMerchantSell) D(OP_ApplyPoison) -D(OP_AugmentInfo) D(OP_AugmentItem) D(OP_CastSpell) D(OP_CharacterCreate) diff --git a/common/patches/underfoot_structs.h b/common/patches/underfoot_structs.h index f7716834b..ab263d6c4 100644 --- a/common/patches/underfoot_structs.h +++ b/common/patches/underfoot_structs.h @@ -4160,9 +4160,9 @@ struct ItemQuaternaryBodyStruct struct AugmentInfo_Struct { -/*000*/ uint32 itemid; // id of the solvent needed -/*004*/ uint8 window; // window to display the information in -/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00 +/*000*/ uint32 itemid; // id of the solvent needed +/*004*/ uint8 window; // window to display the information in +/*005*/ uint8 unknown005[71]; // total packet length 76, all the rest were always 00 /*076*/ }; From 3a270dd96abbe9fd2ccd3a3e5bdfbcaf0de52712 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 3 Oct 2014 15:05:20 -0400 Subject: [PATCH 04/10] Moved OP_LootItem slot translation to external handlers in client patch files --- changelog.txt | 1 + common/patches/client62.cpp | 6 ++++-- common/patches/rof.cpp | 6 ++++-- common/patches/sod.cpp | 6 ++++-- common/patches/sof.cpp | 6 ++++-- common/patches/titanium.cpp | 6 ++++-- common/patches/underfoot.cpp | 6 ++++-- 7 files changed, 25 insertions(+), 12 deletions(-) diff --git a/changelog.txt b/changelog.txt index b31afa449..6272d4a69 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 10/03/2014 == Uleat: Fixed Ti(6.2) OP_AugmentInfo translation that I broke (does not currently need and I mis-read a process) +Uleat: Moved client patch OP_LootItem slot translation to external handlers == 10/02/2014 == Uleat: First round of Ti/6.2 translators added - needed for re-enumeration diff --git a/common/patches/client62.cpp b/common/patches/client62.cpp index d9def3dbb..2da492145 100644 --- a/common/patches/client62.cpp +++ b/common/patches/client62.cpp @@ -446,7 +446,7 @@ namespace Client62 OUT(lootee); OUT(looter); - eq->slot_id = emu->slot_id; + eq->slot_id = ServerToClient62CorpseSlot(emu->slot_id); OUT(auto_loot); FINISH_ENCODE(); @@ -1105,7 +1105,7 @@ namespace Client62 IN(lootee); IN(looter); - emu->slot_id = eq->slot_id; + emu->slot_id = Client62ToServerCorpseSlot(eq->slot_id); IN(auto_loot); FINISH_DIRECT_DECODE(); @@ -1317,6 +1317,7 @@ namespace Client62 static inline int16 ServerToClient62CorpseSlot(uint32 ServerCorpse) { //int16 Client62Corpse; + return ServerCorpse; } static inline uint32 Client62ToServerSlot(int16 Client62Slot) @@ -1331,6 +1332,7 @@ namespace Client62 static inline uint32 Client62ToServerCorpseSlot(int16 Client62Corpse) { //uint32 ServerCorpse; + return Client62Corpse; } } // end namespace Client62 diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 581858381..d6eb858e3 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -1423,7 +1423,7 @@ namespace RoF OUT(lootee); OUT(looter); - eq->slot_id = emu->slot_id + 1; + eq->slot_id = ServerToRoFCorpseSlot(emu->slot_id); OUT(auto_loot); FINISH_ENCODE(); @@ -4405,7 +4405,7 @@ namespace RoF IN(lootee); IN(looter); - emu->slot_id = eq->slot_id - 1; + emu->slot_id = RoFToServerCorpseSlot(eq->slot_id); IN(auto_loot); FINISH_DIRECT_DECODE(); @@ -5406,6 +5406,7 @@ namespace RoF static inline uint32 ServerToRoFCorpseSlot(uint32 ServerCorpse) { //uint32 RoFCorpse; + return (ServerCorpse + 1); } static inline uint32 RoFToServerSlot(structs::ItemSlotStruct RoFSlot) @@ -5546,6 +5547,7 @@ namespace RoF static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse) { //uint32 ServerCorpse; + return (RoFCorpse - 1); } } // end namespace RoF diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 90c5644fe..3501e73f0 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -984,7 +984,7 @@ namespace SoD OUT(lootee); OUT(looter); - eq->slot_id = emu->slot_id + 1; + eq->slot_id = ServerToSoDCorpseSlot(emu->slot_id); OUT(auto_loot); FINISH_ENCODE(); @@ -2956,7 +2956,7 @@ namespace SoD IN(lootee); IN(looter); - emu->slot_id = eq->slot_id - 1; + emu->slot_id = SoDToServerCorpseSlot(eq->slot_id); IN(auto_loot); FINISH_DIRECT_DECODE(); @@ -3599,6 +3599,7 @@ namespace SoD static inline uint32 ServerToSoDCorpseSlot(uint32 ServerCorpse) { //uint32 SoDCorpse; + return (ServerCorpse + 1); } static inline uint32 SoDToServerSlot(uint32 SoDSlot) @@ -3623,6 +3624,7 @@ namespace SoD static inline uint32 SoDToServerCorpseSlot(uint32 SoDCorpse) { //uint32 ServerCorpse; + return (SoDCorpse - 1); } } // end namespace SoD diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 861edcb3d..80c0cb7cf 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -783,7 +783,7 @@ namespace SoF OUT(lootee); OUT(looter); - eq->slot_id = emu->slot_id + 1; + eq->slot_id = ServerToSoFCorpseSlot(emu->slot_id); OUT(auto_loot); FINISH_ENCODE(); @@ -2294,7 +2294,7 @@ namespace SoF IN(lootee); IN(looter); - emu->slot_id = eq->slot_id - 1; + emu->slot_id = SoFToServerCorpseSlot(eq->slot_id); IN(auto_loot); FINISH_DIRECT_DECODE(); @@ -2920,6 +2920,7 @@ namespace SoF static inline uint32 ServerToSoFCorpseSlot(uint32 ServerCorpse) { //uint32 SoFCorpse; + return (ServerCorpse + 1); } static inline uint32 SoFToServerSlot(uint32 SoFSlot) @@ -2945,6 +2946,7 @@ namespace SoF static inline uint32 SoFToServerCorpseSlot(uint32 SoFCorpse) { //uint32 ServerCorpse; + return (SoFCorpse - 1); } } // end namespace SoF diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index d0235049d..7c990751d 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -654,7 +654,7 @@ namespace Titanium OUT(lootee); OUT(looter); - eq->slot_id = emu->slot_id; + eq->slot_id = ServerToTitaniumCorpseSlot(emu->slot_id); OUT(auto_loot); FINISH_ENCODE(); @@ -1517,7 +1517,7 @@ namespace Titanium IN(lootee); IN(looter); - emu->slot_id = eq->slot_id; + emu->slot_id = TitaniumToServerCorpseSlot(eq->slot_id); IN(auto_loot); FINISH_DIRECT_DECODE(); @@ -1745,6 +1745,7 @@ namespace Titanium static inline int16 ServerToTitaniumCorpseSlot(uint32 ServerCorpse) { //int16 TitaniumCorpse; + return ServerCorpse; } static inline uint32 TitaniumToServerSlot(int16 TitaniumSlot) @@ -1759,6 +1760,7 @@ namespace Titanium static inline uint32 TitaniumToServerCorpseSlot(int16 TitaniumCorpse) { //uint32 ServerCorpse; + return TitaniumCorpse; } } // end namespace Titanium diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 0cec336b2..7c1aa940b 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -1234,7 +1234,7 @@ namespace Underfoot OUT(lootee); OUT(looter); - eq->slot_id = emu->slot_id + 1; + eq->slot_id = ServerToUnderFootCorpseSlot(emu->slot_id); OUT(auto_loot); FINISH_ENCODE(); @@ -3294,7 +3294,7 @@ namespace Underfoot IN(lootee); IN(looter); - emu->slot_id = eq->slot_id - 1; + emu->slot_id = UnderfootToServerCorpseSlot(eq->slot_id); IN(auto_loot); FINISH_DIRECT_DECODE(); @@ -4021,6 +4021,7 @@ namespace Underfoot static inline uint32 ServerToUnderFootCorpseSlot(uint32 ServerCorpse) { //uint32 UnderfootCorpse; + return (ServerCorpse + 1); } static inline uint32 UnderfootToServerSlot(uint32 UnderfootSlot) @@ -4046,6 +4047,7 @@ namespace Underfoot static inline uint32 UnderfootToServerCorpseSlot(uint32 UnderfootCorpse) { //uint32 ServerCorpse; + return (UnderfootCorpse - 1); } } // end namespace Underfoot From 61545beff243e272cf6c1db5795450c1328ea450 Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 3 Oct 2014 13:42:39 -0700 Subject: [PATCH 05/10] Hunger and thirst clamping within larger ranges --- zone/client.cpp | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 964f228d1..5b7c0d597 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -39,15 +39,10 @@ extern volatile bool RunLoops; #include "../common/features.h" -#include "masterentity.h" -#include "worldserver.h" #include "../common/misc.h" -#include "zonedb.h" #include "../common/spdat.h" -#include "net.h" #include "../common/packet_dump.h" #include "../common/packet_functions.h" -#include "petitions.h" #include "../common/serverinfo.h" #include "../common/zone_numbers.h" #include "../common/moremath.h" @@ -55,6 +50,12 @@ extern volatile bool RunLoops; #include "../common/breakdowns.h" #include "../common/rulesys.h" #include "../common/string_util.h" +#include "../common/data_verification.h" +#include "net.h" +#include "masterentity.h" +#include "worldserver.h" +#include "zonedb.h" +#include "petitions.h" #include "forage.h" #include "command.h" #include "string_ids.h" @@ -594,19 +595,8 @@ bool Client::Save(uint8 iCommitNow) { database.SaveCharacterTribute(this->CharacterID(), &m_pp); SaveTaskState(); /* Save Character Task */ - if(m_pp.hunger_level < 0) { - m_pp.hunger_level = 0; - } - else if(m_pp.hunger_level > 6000) { - m_pp.hunger_level = 6000; - } - - if(m_pp.thirst_level < 0) { - m_pp.thirst_level = 0; - } - else if(m_pp.thirst_level > 6000) { - m_pp.thirst_level = 6000; - } + m_pp.hunger_level = EQEmu::Clamp(m_pp.hunger_level, 0, 50000); + m_pp.thirst_level = EQEmu::Clamp(m_pp.thirst_level, 0, 50000); database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp, &m_epp); /* Save Character Data */ return true; From e0e305949880536392ecfac7b8c23299ae2a4b75 Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 3 Oct 2014 14:57:01 -0700 Subject: [PATCH 06/10] Turn off user literal error in clang --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f9c5429b..a975ef533 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -259,7 +259,10 @@ OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Import/Export Data Programs." ON) #C++11 stuff IF(NOT MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reserved-user-defined-literal") + ENDIF() ENDIF(NOT MSVC) #Various definitions From e753685ceb3ec1b4a24d80ee657cc89ede7729ce Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 4 Oct 2014 03:23:42 -0400 Subject: [PATCH 07/10] Implement number of hit indicators for UF and RoF There is a small display bug with the initial cast of the spell, but it updates quickly enough that it shouldn't be too noticeable This still needs to be fixed though Changed SendBuffDurationPacket to take a Buffs_Struct by reference to allow more of the data to be obtained without more params Added Client::SendBuffNumHitPacket(Buffs_Struct &buff, int slot) --- common/eq_packet_structs.h | 4 +- common/patches/rof.cpp | 7 +-- common/patches/rof_structs.h | 26 ++++++++++- common/patches/underfoot.cpp | 5 ++- common/patches/underfoot_structs.h | 21 ++++++++- zone/client.h | 3 +- zone/spell_effects.cpp | 70 +++++++++++++----------------- zone/spells.cpp | 38 ++++++++++++---- 8 files changed, 118 insertions(+), 56 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 8e5588e5c..a022626e1 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -534,7 +534,7 @@ struct SpellBuffFade_Struct { /*007*/ uint8 unknown7; /*008*/ uint32 spellid; /*012*/ uint32 duration; -/*016*/ uint32 unknown016; +/*016*/ uint32 num_hits; /*020*/ uint32 unknown020; //prolly global player ID /*024*/ uint32 slotid; /*028*/ uint32 bufffade; @@ -4602,11 +4602,13 @@ struct BuffIconEntry_Struct uint32 buff_slot; uint32 spell_id; uint32 tics_remaining; + uint32 num_hits; }; struct BuffIcon_Struct { uint32 entity_id; + uint8 all_buffs; uint16 count; BuffIconEntry_Struct entries[0]; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index d6eb858e3..a107a1246 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -376,6 +376,7 @@ namespace RoF OUT(duration); eq->playerId = 0x7cde; OUT(slotid); + OUT(num_hits); if (emu->bufffade == 1) eq->bufffade = 1; else @@ -414,7 +415,7 @@ namespace RoF __packet->WriteUInt32(emu->entity_id); __packet->WriteUInt32(0); // PlayerID ? - __packet->WriteUInt8(1); // 1 indicates all buffs on the player (0 to add or remove a single buff) + __packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff) __packet->WriteUInt16(emu->count); for (uint16 i = 0; i < emu->count; ++i) @@ -429,10 +430,10 @@ namespace RoF __packet->WriteUInt32(buffslot); __packet->WriteUInt32(emu->entries[i].spell_id); __packet->WriteUInt32(emu->entries[i].tics_remaining); - __packet->WriteUInt32(0); // Unknown + __packet->WriteUInt32(emu->entries[i].num_hits); // Unknown __packet->WriteString(""); } - __packet->WriteUInt8(0); // Unknown + __packet->WriteUInt8(!emu->all_buffs); // Unknown FINISH_ENCODE(); } diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 0549b4b58..5f1d2aac4 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -712,7 +712,8 @@ struct SpellBuffFade_Struct_Live { /*012*/ uint32 spellid; /*016*/ uint32 duration; /*020*/ uint32 playerId; // Global player ID? -/*024*/ uint8 unknown0028[68]; +/*024*/ uint32 num_hits; +/*028*/ uint8 unknown0028[64]; /*092*/ uint32 slotid; /*096*/ uint32 bufffade; /*100*/ @@ -726,7 +727,7 @@ struct SpellBuffFade_Struct { /*007*/ uint8 unknown7; /*008*/ uint32 spellid; /*012*/ uint32 duration; -/*016*/ uint32 unknown016; +/*016*/ uint32 num_hits; /*020*/ uint32 unknown020; // Global player ID? /*024*/ uint32 playerId; // Player id who cast the buff /*028*/ uint32 slotid; @@ -741,6 +742,27 @@ struct BuffRemoveRequest_Struct /*08*/ }; +#if 0 +// not in use +struct BuffIconEntry_Struct { +/*000*/ uint32 buff_slot; +/*004*/ uint32 spell_id; +/*008*/ uint32 tics_remaining; +/*012*/ uint32 num_hits; +// char name[0]; caster name is also here sometimes +// uint8 unknownend; 1 when single, 0 when all opposite of all_buffs? +}; + +// not in use +struct BuffIcon_Struct { +/*000*/ uint32 entity_id; +/*004*/ uint32 unknown004; +/*008*/ uint8 all_buffs; // 1 when updating all buffs, 0 when doing one +/*009*/ uint16 count; +/*011*/ BuffIconEntry_Struct entires[0]; +}; +#endif + struct GMTrainee_Struct { /*000*/ uint32 npcid; diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 7c1aa940b..6291d3077 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -330,6 +330,7 @@ namespace Underfoot OUT(duration); OUT(slotid); OUT(bufffade); // Live (October 2011) sends a 2 rather than 0 when a buff is created, but it doesn't seem to matter. + OUT(num_hits); eq->unknown008 = 1.0f; FINISH_ENCODE(); @@ -348,7 +349,7 @@ namespace Underfoot *((uint32*)ptr) = emu->entity_id; ptr += sizeof(uint32); ptr += sizeof(uint32); - *((uint8*)ptr) = 1; + *((uint8*)ptr) = emu->all_buffs; ptr += sizeof(uchar); *((uint16*)ptr) = emu->count; ptr += sizeof(uint16); @@ -371,7 +372,9 @@ namespace Underfoot ptr += sizeof(uint32); *((uint32*)ptr) = emu->entries[i].tics_remaining; ptr += sizeof(uint32); + *((uint32*)ptr) = emu->entries[i].num_hits; ptr += sizeof(uint32); + *((uint8*)ptr) = !emu->all_buffs; ptr += 1; } diff --git a/common/patches/underfoot_structs.h b/common/patches/underfoot_structs.h index ab263d6c4..89101ca2e 100644 --- a/common/patches/underfoot_structs.h +++ b/common/patches/underfoot_structs.h @@ -564,7 +564,7 @@ struct SpellBuffFade_Struct_Underfoot { /*008*/ float unknown008; /*012*/ uint32 spellid; /*016*/ uint32 duration; -/*020*/ uint32 unknown016; +/*020*/ uint32 num_hits; /*024*/ uint32 playerId; // Global player ID? /*028*/ uint32 unknown020; /*032*/ uint8 unknown0028[48]; @@ -589,6 +589,25 @@ struct SpellBuffFade_Struct { /*036*/ }; +#if 0 +struct BuffIconEntry_Struct { +/*000*/ uint32 buff_slot; +/*004*/ uint32 spell_id; +/*008*/ uint32 tics_remaining; +/*012*/ uint32 num_hits; +// char name[0]; caster name is also here sometimes +// uint8 unknownend; 1 when single, 0 when all opposite of all_buffs? +}; + +struct BuffIcon_Struct { +/*000*/ uint32 entity_id; +/*004*/ uint32 unknown004; +/*008*/ uint8 all_buffs; // 1 when updating all buffs, 0 when doing one +/*009*/ uint16 count; +/*011*/ BuffIconEntry_Struct entires[0]; +}; +#endif + struct BuffRemoveRequest_Struct { /*00*/ uint32 SlotID; diff --git a/zone/client.h b/zone/client.h index 235861396..fe05194bc 100644 --- a/zone/client.h +++ b/zone/client.h @@ -896,7 +896,8 @@ public: //This is used to later set the buff duration of the spell, in slot to duration. //Doesn't appear to work directly after the client recieves an action packet. - void SendBuffDurationPacket(uint16 spell_id, int duration, int inlevel); + void SendBuffDurationPacket(Buffs_Struct &buff); + void SendBuffNumHitPacket(Buffs_Struct &buff, int slot); void ProcessInspectRequest(Client* requestee, Client* requester); bool ClientFinishedLoading() { return (conn_state == ClientConnectFinished); } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index add06714b..f86f43bf4 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3395,7 +3395,7 @@ void Mob::BuffProcess() { if(buffs[buffs_i].UpdateClient == true) { - CastToClient()->SendBuffDurationPacket(buffs[buffs_i].spellid, buffs[buffs_i].ticsremaining, buffs[buffs_i].casterlevel); + CastToClient()->SendBuffDurationPacket(buffs[buffs_i]); buffs[buffs_i].UpdateClient = false; } } @@ -5559,64 +5559,56 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id) uint32 buff_max = GetMaxTotalSlots(); //Spell specific procs [Type 7,10,11] - if (IsValidSpell(spell_id)){ - - for(uint32 d = 0; d < buff_max; d++) { - - if((buffs[d].spellid == spell_id) && (buffs[d].numhits > 0) && (spells[buffs[d].spellid].numhitstype == type)){ - - if(--buffs[d].numhits == 0) { + if (IsValidSpell(spell_id)) { + for (uint32 d = 0; d < buff_max; d++) { + if (buffs[d].spellid == spell_id && buffs[d].numhits > 0 && + spells[buffs[d].spellid].numhitstype == type) { + if (--buffs[d].numhits == 0) { CastOnNumHitFade(buffs[d].spellid); - if(!TryFadeEffect(d)) + if (!TryFadeEffect(d)) BuffFadeBySlot(d, true); + } else if (IsClient()) { // still have numhits and client, update + CastToClient()->SendBuffNumHitPacket(buffs[d], d); } } } - } - - else if (type == 7){ - if (buff_slot > 0){ - - if(--buffs[buff_slot].numhits == 0) { + } else if (type == 7) { + if (buff_slot > 0) { + if (--buffs[buff_slot].numhits == 0) { CastOnNumHitFade(buffs[buff_slot].spellid); - if(!TryFadeEffect(buff_slot)) + if (!TryFadeEffect(buff_slot)) BuffFadeBySlot(buff_slot , true); - } + } else if (IsClient()) { // still have numhits and client, update + CastToClient()->SendBuffNumHitPacket(buffs[buff_slot], buff_slot); } - - else { - - for(int d = 0; d < buff_max; d++) { - - if(!m_spellHitsLeft[d]) + } else { + for (int d = 0; d < buff_max; d++) { + if (!m_spellHitsLeft[d]) continue; - if ((IsValidSpell(buffs[d].spellid)) && (m_spellHitsLeft[d] == buffs[d].spellid)) { - if(--buffs[d].numhits == 0) { + if (IsValidSpell(buffs[d].spellid) && m_spellHitsLeft[d] == buffs[d].spellid) { + if (--buffs[d].numhits == 0) { CastOnNumHitFade(buffs[d].spellid); m_spellHitsLeft[d] = 0; - if(!TryFadeEffect(d)) + if (!TryFadeEffect(d)) BuffFadeBySlot(d, true); + } else if (IsClient()) { // still have numhits and client, update + CastToClient()->SendBuffNumHitPacket(buffs[d], d); } } } } - } - - - else{ - - for(uint32 d = 0; d < buff_max; d++) { - - if((IsValidSpell(buffs[d].spellid)) && (buffs[d].numhits > 0) && (spells[buffs[d].spellid].numhitstype == type)){ - - if(--buffs[d].numhits == 0) { + } else { + for (uint32 d = 0; d < buff_max; d++) { + if (IsValidSpell(buffs[d].spellid) && buffs[d].numhits > 0 && + spells[buffs[d].spellid].numhitstype == type) { + if (--buffs[d].numhits == 0) { CastOnNumHitFade(buffs[d].spellid); - if(!TryFadeEffect(d)){ + if (!TryFadeEffect(d)) BuffFadeBySlot(d, true); - } + } else if (IsClient()) { // still have numhits and client, update + CastToClient()->SendBuffNumHitPacket(buffs[d], d); } - } } } diff --git a/zone/spells.cpp b/zone/spells.cpp index fb3cba454..310bc35bd 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5164,20 +5164,40 @@ void Mob::_StopSong() //Thus I use this in the buff process to update the correct duration once after casting //this allows AAs and focus effects that increase buff duration to work correctly, but could probably //be used for other things as well -void Client::SendBuffDurationPacket(uint16 spell_id, int duration, int inlevel) +void Client::SendBuffDurationPacket(Buffs_Struct &buff) { EQApplicationPacket* outapp; outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffFade_Struct)); SpellBuffFade_Struct* sbf = (SpellBuffFade_Struct*) outapp->pBuffer; sbf->entityid = GetID(); - sbf->slot=2; - sbf->spellid=spell_id; - sbf->slotid=0; - sbf->effect = inlevel > 0 ? inlevel : GetLevel(); - sbf->level = inlevel > 0 ? inlevel : GetLevel(); + sbf->slot = 2; + sbf->spellid = buff.spellid; + sbf->slotid = 0; + sbf->effect = buff.casterlevel > 0 ? buff.casterlevel : GetLevel(); + sbf->level = buff.casterlevel > 0 ? buff.casterlevel : GetLevel(); sbf->bufffade = 0; - sbf->duration = duration; + sbf->duration = buff.ticsremaining; + sbf->num_hits = buff.numhits; + FastQueuePacket(&outapp); +} + +void Client::SendBuffNumHitPacket(Buffs_Struct &buff, int slot) +{ + // UF+ use this packet + if (GetClientVersion() < EQClientUnderfoot) + return; + EQApplicationPacket *outapp; + outapp = new EQApplicationPacket(OP_BuffCreate, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct)); + BuffIcon_Struct *bi = (BuffIcon_Struct *)outapp->pBuffer; + bi->entity_id = GetID(); + bi->count = 1; + bi->all_buffs = 0; + + bi->entries[0].buff_slot = slot; + bi->entries[0].spell_id = buff.spellid; + bi->entries[0].tics_remaining = buff.ticsremaining; + bi->entries[0].num_hits = buff.numhits; FastQueuePacket(&outapp); } @@ -5252,6 +5272,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) BuffIcon_Struct *buff = (BuffIcon_Struct*)outapp->pBuffer; buff->entity_id = GetID(); buff->count = count; + buff->all_buffs = 1; uint32 index = 0; for(unsigned int i = 0; i < buff_count; ++i) @@ -5261,6 +5282,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) buff->entries[index].buff_slot = i; buff->entries[index].spell_id = buffs[i].spellid; buff->entries[index].tics_remaining = buffs[i].ticsremaining; + buff->entries[index].num_hits = buffs[i].numhits; ++index; } } @@ -5278,7 +5300,7 @@ void Mob::BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration) buffs[i].ticsremaining = newDuration; if(IsClient()) { - CastToClient()->SendBuffDurationPacket(buffs[i].spellid, buffs[i].ticsremaining, buffs[i].casterlevel); + CastToClient()->SendBuffDurationPacket(buffs[i]); } } } From 806a9fbb99cafeddeaffc58f758067d65d8c8d27 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 4 Oct 2014 23:38:20 -0400 Subject: [PATCH 08/10] Identified recast timer field in Ti item packet header --- common/patches/client62.cpp | 1 + common/patches/titanium.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/patches/client62.cpp b/common/patches/client62.cpp index 2da492145..5afd76bcd 100644 --- a/common/patches/client62.cpp +++ b/common/patches/client62.cpp @@ -1234,6 +1234,7 @@ namespace Client62 int i; uint32 sub_length; + // not sure if 6.2 has a recast timer timestamp field..but, something seems amiss between this and Ti's ordering MakeAnyLenString(&instance, "%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|", stackable ? charges : 1, diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 7c990751d..6c2591efe 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1675,7 +1675,7 @@ namespace Titanium 0, //merchant_slot, //instance ID, bullshit for now (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot, - 0, + 0, // item recast timer timestamp field (aka..last_cast_time field in SoF+ clients) (stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : charges), inst->IsInstNoDrop() ? 1 : 0, 0 From 7dc1da21f0a892dcdddb2880e425a4bba7657ec9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Oct 2014 02:18:30 -0400 Subject: [PATCH 09/10] Move OP_ItemRecastDelay to after cast I originally assumed it needed to be sent "while casting" but it looks like right at the end (where we set the reuse timer) also works. --- zone/spells.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 310bc35bd..9ca3965cc 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -484,19 +484,6 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, return false; } - // This needs a bit more work for saving timer to PP for zoning etc - if (IsClient() && item_slot != INVALID_INDEX && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT))) { - ItemInst *itm = CastToClient()->GetInv().GetItem(item_slot); - if (itm && itm->GetItem()->RecastDelay) { - outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct)); - ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer; - ird->recast_delay = itm->GetItem()->RecastDelay; - ird->recast_type = itm->GetItem()->RecastType; - CastToClient()->QueuePacket(outapp); - safe_delete(outapp); - } - } - return(true); } @@ -2228,6 +2215,12 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 ItemInst *itm = CastToClient()->GetInv().GetItem(inventory_slot); if(itm && itm->GetItem()->RecastDelay > 0){ CastToClient()->GetPTimers().Start((pTimerItemStart + itm->GetItem()->RecastType), itm->GetItem()->RecastDelay); + EQApplicationPacket *outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct)); + ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer; + ird->recast_delay = itm->GetItem()->RecastDelay; + ird->recast_type = itm->GetItem()->RecastType; + CastToClient()->QueuePacket(outapp); + safe_delete(outapp); } } From 4f2dbb37d26f9b4ab418e63cd65381095cac928d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Oct 2014 02:28:17 -0400 Subject: [PATCH 10/10] Confirmed OP_ItemRecastDelay for SoF --- utils/patches/patch_SoF.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 5bffdfc93..2e039b404 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -615,6 +615,8 @@ OP_RAWOutOfSession=0x0000 # OP_Some3ByteHPUpdate=0x0000 #initial HP update for mobs OP_InitialHPUpdate=0x0000 # +OP_ItemRecastDelay=0x0ada + # Opcodes from the client that are currently Unknowns: # 0x3E85 - Sent when Guild Management window is opened